Compare commits

..

145 Commits

Author SHA1 Message Date
Paweł Banaszewski d4c7cb2021 feat(aibridged): add overload protection with rate limiting and concurrency control
This adds configurable overload protection to the AI Bridge daemon to prevent
the server from being overwhelmed during periods of high load.

New configuration options:
- CODER_AIBRIDGE_MAX_CONCURRENCY: Maximum number of concurrent AI Bridge requests (0 to disable)
- CODER_AIBRIDGE_RATE_LIMIT: Maximum number of requests per rate window (0 to disable)
- CODER_AIBRIDGE_RATE_WINDOW: Duration of the rate limiting window (default: 1m)

When limits are exceeded:
- Concurrency limit: Returns HTTP 503 Service Unavailable
- Rate limit: Returns HTTP 429 Too Many Requests

The overload protection middleware wraps the aibridged HTTP handler and provides:
- Concurrency limiting using an atomic counter
- Rate limiting using the go-chi/httprate library

Both protections are optional and disabled by default (0 values).

Fixes coder/internal#1153
2025-12-08 11:17:58 +00:00
Jake Howell 25400fedca fix: update colors and theme in error.html (#20941)
### Description

This pull-request ensures that we're using the right colors (and
themeing things within the actual coder brand) on the `error.html` page.
Furthermore, I went ahead and cleaned up the CSS Variables and converted
all `px` units to a standard `rem` unit (16px base).

### Preview

<img width="3516" height="2388" alt="CleanShot 2025-12-02 at 11 09
55@2x"
src="https://github.com/user-attachments/assets/781623ea-a487-4a2e-a08e-bec86d6de6f5"
/>
2025-12-08 14:32:18 +11:00
Andrew Aquino 82bb833099 docs: update AI Bridge description for H2 2025 (#21126)
@suman-bisht This file is the source for docs pages' SEO description +
automatically generated preview image on coder.com
2025-12-05 14:36:39 -08:00
Mathias Fredriksson 61beb7bfa8 docs: rewrite dev containers documentation for GA (#21080)
docs: rewrite dev containers documentation for GA

Corrects inaccuracies in SSH examples (deprecated `--container` flag),
port forwarding (native sub-agent forwarding is primary), and
prerequisites (dev containers are on by default). Fixes template
descriptions: docker-devcontainer uses native Dev Containers while
AWS/Kubernetes templates use Envbuilder.

Renames admin docs folder from `devcontainers/` to `envbuilder/` to
reflect actual content. Adds customization guide documenting agent
naming, display apps, custom apps, and variable interpolation. Documents
multi-repo workspace support and adds note about Terraform module
limitations with sub-agents. Fixes module registry URLs.

Refs #18907
2025-12-05 19:42:16 +02:00
blinkagent[bot] b4be5bcfed docs: fix swagger tags for license endpoints (#21101)
## Summary

Change `@Tags` from `Organizations` to `Enterprise` for `POST /licenses`
and `POST /licenses/refresh-entitlements` to match the `GET` and
`DELETE` license endpoints which are already tagged as `Enterprise`.

## Problem

The license API endpoints were inconsistently tagged in the swagger
annotations:
- `GET /licenses` → `Enterprise` ✓
- `DELETE /licenses/{id}` → `Enterprise` ✓
- `POST /licenses` → `Organizations` ✗
- `POST /licenses/refresh-entitlements` → `Organizations` ✗

This caused the POST endpoints to be documented in the [Organizations
API docs](https://coder.com/docs/reference/api/organizations) instead of
the [Enterprise API
docs](https://coder.com/docs/reference/api/enterprise) where the other
license endpoints live.

## Fix

Simply updated the `@Tags` annotation from `Organizations` to
`Enterprise` for both POST endpoints.

This was an oversight from the original swagger docs addition in #5625
(January 2023).

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2025-12-05 15:27:22 +00:00
dependabot[bot] ceaba0778e chore: bump github.com/brianvoe/gofakeit/v7 from 7.9.0 to 7.12.1 (#21096)
Bumps
[github.com/brianvoe/gofakeit/v7](https://github.com/brianvoe/gofakeit)
from 7.9.0 to 7.12.1.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/6cb292655fc27bb9c5d81cb2bf2c5596313740e3"><code>6cb2926</code></a>
go mod - change back to 1.22</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/5a2657afecd681df23c4dd8664216db5fe26c805"><code>5a2657a</code></a>
lookup - updated keywords to not have the display name in the keywords
list</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/67d31c1b536d7bfe3e8a34d954afc6e9583b15ff"><code>67d31c1</code></a>
person - added ethnicity</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/ae0414ce24587529911ca8de6b886d7d9810c0ef"><code>ae0414c</code></a>
lookup - added test to make sure display is not in keywords</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/6f01995ab4278531359da913268f2e058becbb92"><code>6f01995</code></a>
user agent - added api user agent</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/e4c26beca835cc4262566104db199c6061ae02d2"><code>e4c26be</code></a>
person - added age</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/dcf08aee21636c27ef87ca9b4b5424af85fa4991"><code>dcf08ae</code></a>
funclookup concurrency - cleaned up focused verbage more on concurrency.
also...</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/1a45942dacb4b0b98d3e7e563033f87f1d34c364"><code>1a45942</code></a>
Merge pull request <a
href="https://redirect.github.com/brianvoe/gofakeit/issues/390">#390</a>
from AdamDrewsTR/race-conditions-fix</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/c03d3c83a271e9d543eab20387263adfd639037b"><code>c03d3c8</code></a>
fix: resolve concurrent map read/write race conditions by implementing
RWMute...</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/a0380da0d95ea14b94e21a7a1d953e595eb5226f"><code>a0380da</code></a>
refactor: consolidate race condition tests into concurrency_test.go and
remov...</li>
<li>Additional commits viewable in <a
href="https://github.com/brianvoe/gofakeit/compare/v7.9.0...v7.12.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/brianvoe/gofakeit/v7&package-manager=go_modules&previous-version=7.9.0&new-version=7.12.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-05 15:13:33 +00:00
Paweł Banaszewski e24cc5e6da feat: add tracing to aibridge (#21106)
Adds tracing for AIBridge.
Updates github.com/coder/aibridge version from `v0.2.2` to `v0.3.0`

Depends on: https://github.com/coder/aibridge/pull/63
Fixes: https://github.com/coder/aibridge/issues/26

---------

Co-authored-by: Danny Kopping <danny@coder.com>
2025-12-05 15:59:52 +01:00
Danny Kopping 259dee2ea8 fix: move contexts to appropriate locations (#21121)
Closes https://github.com/coder/internal/issues/1173,
https://github.com/coder/internal/issues/1174

Currently these two tests are flaky because the contexts were created
before a potentially long-running process. By the time the context was
actually used, it may have timed out - leading to confusion.

Additionally, the `ExpectMatch` calls were not using the test context -
but rather a background context. I've marked that func as deprecated
because we should always tie these to the test context.

Special thanks to @mafredri for the brain probe 🧠

---------

Signed-off-by: Danny Kopping <danny@coder.com>
2025-12-05 13:14:35 +00:00
DevCats 8e0516a19c chore: add support for antigravity external app protocol (#20873)
Adds `antigravity` to the allowed protocols list.

Related PR:
https://github.com/coder/registry/pull/558
2025-12-05 13:09:58 +00:00
Jakub Domeracki 770fdb377c chore: update react to apply patch for CVE-2025-55182 (#21084)
Reference:

https://react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components
2025-12-05 09:49:59 +01:00
Callum Styan 83dbf73dde perf: don't calculate build times for deleted templates (#21072)
The metrics cache to calculate and expose build time metrics for
templates currently calls `GetTemplates`, which returns all templates
even if they are deleted. We can use the `GetTemplatesWithFilter` query
to easily filter out deleted templates from the results, and thus not
call `GetTemplateAverageBuildTime` for those deleted templates. Delete
time for workspaces for non-deleted templates is still calculated.

Signed-off-by: Callum Styan <callumstyan@gmail.com>
2025-12-04 10:27:56 -08:00
Mathias Fredriksson 0ab23abb19 refactor(site): convert workspace batch delete dialog to Tailwind CSS (#20946)
Converts from Emotion to Tailwind CSS, based on the tasks batch delete
dialog implementation.

Also propagates simplifications back to the tasks dialog:
- Use `border-border` instead of hardcoded color variants
- Use `max-h-48` instead of specific `max-h-[184px]`
- Add cancel button to workspaces dialog

Refs #20905
2025-12-04 20:10:21 +02:00
david-fraley c4bf5a2d81 docs: add ESR to Release Channels (#21060) 2025-12-04 11:43:32 -06:00
Mathias Fredriksson 5cb02a6cc0 refactor(site): remove redundant client-side sorting of app statuses (#21102)
Depends on #21099
2025-12-04 18:55:45 +02:00
Mathias Fredriksson cfdd4a9b88 perf(coderd/database): add index on workspace_app_statuses.app_id (#21099) 2025-12-04 17:56:13 +02:00
Mathias Fredriksson d9159103cd fix(agent/agentcontainers): broadcast devcontainer dirty status over websocket (#21100) 2025-12-04 16:11:03 +02:00
Mathias Fredriksson 532a1f3054 fix(coderd): exclude sub-agents from workspace health calculation (#21098) 2025-12-04 15:38:24 +02:00
dependabot[bot] 6aeb144a98 chore: bump google.golang.org/api from 0.256.0 to 0.257.0 (#21094)
Bumps
[google.golang.org/api](https://github.com/googleapis/google-api-go-client)
from 0.256.0 to 0.257.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/releases">google.golang.org/api's
releases</a>.</em></p>
<blockquote>
<h2>v0.257.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.256.0...v0.257.0">0.257.0</a>
(2025-12-02)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3376">#3376</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/b0c07d2f5cc4aa2cf974c2938508626f8430855e">b0c07d2</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3380">#3380</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/47fcc39088f806c4202ca47159416ce99a0a0c72">47fcc39</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3381">#3381</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/cf5cf20d07fac3acc66c1f9ade705bb99701519a">cf5cf20</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3382">#3382</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/2931d4b217c6934f85bdc378ebbbbe4fa54db96d">2931d4b</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3383">#3383</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/446402e7d6aedbe169505c07aafcf45e96563a8e">446402e</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3384">#3384</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/d82a5d02f83b3455f747cbb1fb14930703dad60e">d82a5d0</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3386">#3386</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/6a0b46d49312d528dab4dce8daee48866f38ba25">6a0b46d</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3387">#3387</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/f3dc8f4bd57ade8c6ffb37cda8d55289228ebcd1">f3dc8f4</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3388">#3388</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/e3ca7fd5738afd1a8aa046431ef005c48e701358">e3ca7fd</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3389">#3389</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/b78dd96b2c603926daca6c30baae9c4843bf5664">b78dd96</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md">google.golang.org/api's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.256.0...v0.257.0">0.257.0</a>
(2025-12-02)</h2>
<h3>Features</h3>
<ul>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3376">#3376</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/b0c07d2f5cc4aa2cf974c2938508626f8430855e">b0c07d2</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3380">#3380</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/47fcc39088f806c4202ca47159416ce99a0a0c72">47fcc39</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3381">#3381</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/cf5cf20d07fac3acc66c1f9ade705bb99701519a">cf5cf20</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3382">#3382</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/2931d4b217c6934f85bdc378ebbbbe4fa54db96d">2931d4b</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3383">#3383</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/446402e7d6aedbe169505c07aafcf45e96563a8e">446402e</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3384">#3384</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/d82a5d02f83b3455f747cbb1fb14930703dad60e">d82a5d0</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3386">#3386</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/6a0b46d49312d528dab4dce8daee48866f38ba25">6a0b46d</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3387">#3387</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/f3dc8f4bd57ade8c6ffb37cda8d55289228ebcd1">f3dc8f4</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3388">#3388</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/e3ca7fd5738afd1a8aa046431ef005c48e701358">e3ca7fd</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3389">#3389</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/b78dd96b2c603926daca6c30baae9c4843bf5664">b78dd96</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/3e8573d81048b9abb10fe28e0cbe9623fdb4668a"><code>3e8573d</code></a>
chore(main): release 0.257.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3377">#3377</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/61592252846bfa757ebd4a68e461bd96381984cf"><code>6159225</code></a>
chore(all): update all to 79d6a2a (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3390">#3390</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/b78dd96b2c603926daca6c30baae9c4843bf5664"><code>b78dd96</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3389">#3389</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/e3ca7fd5738afd1a8aa046431ef005c48e701358"><code>e3ca7fd</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3388">#3388</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/f3dc8f4bd57ade8c6ffb37cda8d55289228ebcd1"><code>f3dc8f4</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3387">#3387</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/6a0b46d49312d528dab4dce8daee48866f38ba25"><code>6a0b46d</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3386">#3386</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/a07da21fe2e45130d2e9cb1494f98a7fe2420ba1"><code>a07da21</code></a>
chore(deps): bump golang.org/x/crypto from 0.43.0 to 0.45.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3379">#3379</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/35b0966d9ce6b797c6e63730066ecec3292ade34"><code>35b0966</code></a>
chore(deps): bump golang.org/x/crypto from 0.37.0 to 0.45.0 in
/internal/koko...</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/d82a5d02f83b3455f747cbb1fb14930703dad60e"><code>d82a5d0</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3384">#3384</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/8c1e205890063d558cb41bfc1bf806a9385c2126"><code>8c1e205</code></a>
chore(all): update all (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3374">#3374</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/googleapis/google-api-go-client/compare/v0.256.0...v0.257.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/api&package-manager=go_modules&previous-version=0.256.0&new-version=0.257.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-04 10:27:14 +00:00
dependabot[bot] f94d8fc019 chore: bump github.com/aws/smithy-go from 1.23.2 to 1.24.0 (#21095)
Bumps [github.com/aws/smithy-go](https://github.com/aws/smithy-go) from
1.23.2 to 1.24.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/aws/smithy-go/blob/main/CHANGELOG.md">github.com/aws/smithy-go's
changelog</a>.</em></p>
<blockquote>
<h1>Release (2025-12-01)</h1>
<h2>General Highlights</h2>
<ul>
<li><strong>Dependency Update</strong>: Updated to the latest SDK module
versions</li>
</ul>
<h2>Module Highlights</h2>
<ul>
<li><code>github.com/aws/smithy-go</code>: v1.24.0
<ul>
<li><strong>Feature</strong>: Improve allocation footprint of the
middleware stack. This should convey a ~10% reduction in allocations per
SDK request.</li>
</ul>
</li>
</ul>
<h1>Release (2025-11-03)</h1>
<h2>General Highlights</h2>
<ul>
<li><strong>Dependency Update</strong>: Updated to the latest SDK module
versions</li>
</ul>
<h2>Module Highlights</h2>
<ul>
<li><code>github.com/aws/smithy-go</code>: v1.23.2
<ul>
<li><strong>Bug Fix</strong>: Adjust the initial sizes of each
middleware phase to avoid some unnecessary reallocation.</li>
<li><strong>Bug Fix</strong>: Avoid unnecessary allocation overhead from
the metrics system when not in use.</li>
</ul>
</li>
</ul>
<h1>Release (2025-10-15)</h1>
<h2>General Highlights</h2>
<ul>
<li><strong>Dependency Update</strong>: Bump minimum go version to
1.23.</li>
<li><strong>Dependency Update</strong>: Updated to the latest SDK module
versions</li>
</ul>
<h1>Release (2025-09-18)</h1>
<h2>Module Highlights</h2>
<ul>
<li><code>github.com/aws/smithy-go/aws-http-auth</code>: <a
href="https://github.com/aws/smithy-go/blob/main/aws-http-auth/CHANGELOG.md#v110-2025-09-18">v1.1.0</a>
<ul>
<li><strong>Feature</strong>: Added support for SIG4/SIGV4A querystring
authentication.</li>
</ul>
</li>
</ul>
<h1>Release (2025-08-27)</h1>
<h2>General Highlights</h2>
<ul>
<li><strong>Dependency Update</strong>: Updated to the latest SDK module
versions</li>
</ul>
<h2>Module Highlights</h2>
<ul>
<li><code>github.com/aws/smithy-go</code>: v1.23.0
<ul>
<li><strong>Feature</strong>: Sort map keys in JSON Document types.</li>
</ul>
</li>
</ul>
<h1>Release (2025-07-24)</h1>
<h2>General Highlights</h2>
<ul>
<li><strong>Dependency Update</strong>: Updated to the latest SDK module
versions</li>
</ul>
<h2>Module Highlights</h2>
<ul>
<li><code>github.com/aws/smithy-go</code>: v1.22.5
<ul>
<li><strong>Feature</strong>: Add HTTP interceptors.</li>
</ul>
</li>
</ul>
<h1>Release (2025-06-16)</h1>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/aws/smithy-go/commit/71f5bff362491399f8a2cca586c5802eb5a66d70"><code>71f5bff</code></a>
Release 2025-12-01</li>
<li><a
href="https://github.com/aws/smithy-go/commit/c94c177cfcf46095d48a88253899242f5971ae1b"><code>c94c177</code></a>
changelog</li>
<li><a
href="https://github.com/aws/smithy-go/commit/0cc0b1c115aede116e0a5b901f195fef2ea2567a"><code>0cc0b1c</code></a>
convert middleware steps to linked lists (<a
href="https://redirect.github.com/aws/smithy-go/issues/617">#617</a>)</li>
<li><a
href="https://github.com/aws/smithy-go/commit/ed49224f03828a26529458a48ff56b9b0b4db45e"><code>ed49224</code></a>
Add param binding error check in auth scheme resolution to avoid panic
(<a
href="https://redirect.github.com/aws/smithy-go/issues/619">#619</a>)</li>
<li><a
href="https://github.com/aws/smithy-go/commit/0e0b20cb123137d985083894df55fdbdbe3ce332"><code>0e0b20c</code></a>
add discrete tests for initialize step (<a
href="https://redirect.github.com/aws/smithy-go/issues/618">#618</a>)</li>
<li><a
href="https://github.com/aws/smithy-go/commit/ddbac1c617ac6bea513c16923e7883b1439b2a34"><code>ddbac1c</code></a>
only add interceptors if configured (<a
href="https://redirect.github.com/aws/smithy-go/issues/616">#616</a>)</li>
<li><a
href="https://github.com/aws/smithy-go/commit/798bf4fa874b68b13350766bf270d3b868e8abcf"><code>798bf4f</code></a>
remove pointless trace spans (<a
href="https://redirect.github.com/aws/smithy-go/issues/615">#615</a>)</li>
<li><a
href="https://github.com/aws/smithy-go/commit/dc545a769d214b08bd69e93fffc40a962b815c56"><code>dc545a7</code></a>
don't create op metrics context if not in use (<a
href="https://redirect.github.com/aws/smithy-go/issues/613">#613</a>)</li>
<li><a
href="https://github.com/aws/smithy-go/commit/6f12c095f5277d7e682217bcfd50bab607b193ab"><code>6f12c09</code></a>
add host label validation for region before ep resolution (<a
href="https://redirect.github.com/aws/smithy-go/issues/612">#612</a>)</li>
<li>See full diff in <a
href="https://github.com/aws/smithy-go/compare/v1.23.2...v1.24.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/aws/smithy-go&package-manager=go_modules&previous-version=1.23.2&new-version=1.24.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-04 10:26:32 +00:00
dependabot[bot] e93a917c2f chore: bump the coder-modules group across 3 directories with 7 updates (#21093)
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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-04 10:25:01 +00:00
Jakub Domeracki 0f054096e4 chore: enforce cooldown period (#21079)
Closes:
https://github.com/coder/internal/issues/1170

Changes in scope:
- [enforce cooldown
period](https://github.com/coder/coder/commit/829792e37fbe25b119fa658efd6d310dd507d7d6)
- [remove obsolete reviewers
entry](https://github.com/coder/coder/commit/4875992bc6323249353518d4e361b3f7244c8a71)

Reference:

https://github.blog/changelog/2025-04-29-dependabot-reviewers-configuration-option-being-replaced-by-code-owners/
2025-12-04 11:13:19 +01:00
Mathias Fredriksson 2f829286f2 fix(site): simplify bulk task delete confirmation UI (#20979)
Reduce from 3 confirmation stages to 2 by removing the redundant
"resources" stage. The final button now shows "Delete N tasks and M
workspaces" directly, so users still see what will be deleted.

Also add a Cancel button to match the single task delete dialog UX.

Refs #20905
2025-12-04 10:46:02 +02:00
dependabot[bot] 6acfcd5736 chore: bump next from 15.5.6 to 15.5.7 in /offlinedocs (#21086)
Bumps [next](https://github.com/vercel/next.js) from 15.5.6 to 15.5.7.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vercel/next.js/releases">next's
releases</a>.</em></p>
<blockquote>
<h2>v15.5.7</h2>
<p>Please see <a
href="https://nextjs.org/blog/CVE-2025-66478">CVE-2025-66478</a> for
additional details about this release.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vercel/next.js/commit/3eaf68b09b2b6b8c0c8e080a9713e131a78dc529"><code>3eaf68b</code></a>
v15.5.7</li>
<li><a
href="https://github.com/vercel/next.js/commit/8367ce592ad0190ec941dac1ce6d0b5a44606593"><code>8367ce5</code></a>
update version script</li>
<li><a
href="https://github.com/vercel/next.js/commit/9115040008baf255499136933a50084b76f4bfd8"><code>9115040</code></a>
Update React Version for Next.js 15.5.7 (<a
href="https://redirect.github.com/vercel/next.js/issues/10">#10</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/96f699902a5c57293e312591f843080a4d68ee1b"><code>96f6999</code></a>
update tag</li>
<li>See full diff in <a
href="https://github.com/vercel/next.js/compare/v15.5.6...v15.5.7">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=next&package-manager=npm_and_yarn&previous-version=15.5.6&new-version=15.5.7)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts page](https://github.com/coder/coder/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-03 20:03:02 +00:00
Danny Kopping 9e021f7b57 chore: upgrade to aibridge@v0.2.2 (#21085)
Changes from https://github.com/coder/aibridge/pull/71/

Signed-off-by: Danny Kopping <danny@coder.com>
2025-12-03 19:56:50 +00:00
Mathias Fredriksson aa306f2262 docs: add rules to avoid unnecessary changes to CLAUDE.md (#21083) 2025-12-03 20:49:18 +02:00
Danny Kopping fcd64ea7f5 chore: upgrade to aibridge@v0.2.1 (#21082)
Changes from https://github.com/coder/aibridge/pull/70/

Signed-off-by: Danny Kopping <danny@coder.com>
2025-12-03 15:41:12 +00:00
Max Bretschneider 9d7509aeb3 docs: add link to new ROS2 community template (#20902)
Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
2025-12-03 14:36:15 +00:00
Spike Curtis d5bb1361e2 docs: delete references to adding database replicas (#21077)
Removes references to adding database replicas from the scaling docs, as Coder only allows a single connection URL. These passages where added in error.
2025-12-03 16:15:58 +04:00
blink-so[bot] e17b47f9ff docs: restructure docker installation with tabs (#19567)
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Co-authored-by: M Atif Ali <U04T3LN8ASU+atif@users.noreply.github.com>
Co-authored-by: Atif Ali <atif@coder.com>
2025-12-03 17:02:08 +05:00
Spike Curtis 40df21ed62 fix: fixes use of possibly nil RemoteAddr() and LocalAddr() return values (#21076)
fixes: https://github.com/coder/internal/issues/1143

Both gVisor and the Go standard library implementations of `net.Conn` can under certain circumstances return `nil` for `RemoteAddr()` and `LocalAddr()` calls. If we call their methods, we segfault.

This PR fixes these calls and adds ruleguard rules.

Note that `slog.F("remote_addr", conn.RemoteAddr())` is fine because slog detects the `nil` before attempting to stringify the type.
2025-12-03 15:06:00 +04:00
Marcin Tojek 65ef6df1df docs: add documentation for preset invalidation (#21018)
Fixes #17917
2025-12-03 11:43:49 +01:00
Mathias Fredriksson f1b2715555 docs: add data retention and export documentation for AI Bridge (#21055)
Previously AI Bridge retention was only documented in the auto-generated
CLI reference, making it difficult for administrators to discover and
understand how to configure data retention for compliance requirements.

This adds retention configuration to the AI Bridge setup guide with
examples, documents the REST API and CLI export options in the monitoring
guide, and cross-references AI Bridge from the central data retention
page for discoverability.

Closes #21038
2025-12-03 11:39:36 +02:00
Mathias Fredriksson ad93262d07 fix(coderd/database/dbpurge): allow disabling AI Bridge retention with 0 (#21062)
Previously setting AI Bridge retention to 0 would cause records to be
deleted immediately since we didn't check for the zero value before
calculating the deletion threshold.

This adds a check for aibridgeRetention > 0 to skip deletion when
retention is disabled, matching the pattern used for other retention
settings (connection logs, audit logs, etc.).

Also fixes the return type of DeleteOldAIBridgeRecords from int32 to
int64 since COUNT(*) returns bigint in PostgreSQL.

Refs #21055
2025-12-03 09:37:18 +00:00
Mathias Fredriksson c750695d83 feat(cli/cliui): output empty string for empty table (#20967)
This changes makes it so that we output the empty string for Format
when there is no data. It turns out there are many places in the code
where we have such handling, but in a way that would break the JSON
formatter (since we'd output nothing on stdout or text rather than
`[]`/`null`).
2025-12-03 11:32:59 +02:00
Rowan Smith 3c05cb6255 feat: add serviceAccount.labels for custom service account labels on helm chart (#21048)
closes #20541 

adds `coder.serviceAccount.labels` var to support custom labels being
added to the SA.

Current chart:
```
➜  helm-service-account-labels git:(rowansmithau/feat/helm_service_account_labels) helm template coder coder-v2/coder --set coder.image.tag=latest --set coder.serviceAccount.labels.mux=isnice | egrep -A13 '^kind: ServiceAccount$'
kind: ServiceAccount
metadata:
  annotations: {}
  labels:
    app.kubernetes.io/instance: coder
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: coder
    app.kubernetes.io/part-of: coder
    app.kubernetes.io/version: 2.28.3
    helm.sh/chart: coder-2.28.3
  name: coder
  namespace: default
---
# Source: coder/templates/rbac.yaml
```

With this PR:
```
➜  helm-service-account-labels git:(rowansmithau/feat/helm_service_account_labels) helm template coder helm/coder --set coder.image.tag=latest --set coder.serviceAccount.labels.mux=isnice | egrep -A13 '^kind: ServiceAccount$'
kind: ServiceAccount
metadata:
  annotations: {}
  labels:
    app.kubernetes.io/instance: coder
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: coder
    app.kubernetes.io/part-of: coder
    app.kubernetes.io/version: 0.1.0
    helm.sh/chart: coder-0.1.0
    mux: isnice
  name: coder
  namespace: default
---
```

A test with `disableCreate=true` still correctly shows no SA created:
```
➜  helm-service-account-labels git:(rowansmithau/feat/helm_service_account_labels) helm template coder helm/coder --set coder.image.tag=latest --set coder.serviceAccount.labels.mux=isnice --set coder.serviceAccount.disableCreate=true | egrep '^kind: ServiceAccount$'
```
2025-12-03 12:25:39 +11:00
DevCats 18ef78604f feat: add google antigravity ide icon to theme (#21068)
adds google antigravity ide icon to theme:



![antigravity](https://github.com/user-attachments/assets/fa1d3550-8175-40fc-8f12-0042c3e66d69)


There is no need for any transformation with this icon, as it should
look good in dark and light mode.
2025-12-02 15:38:44 -06:00
david-fraley db5ccda1ec chore(docs): update Docs Release Cal for 2.29 (#21069) 2025-12-02 21:06:09 +00:00
blinkagent[bot] 0873d9af6d docs: regenerate feature-stages experiments table (#21024)
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2025-12-03 00:22:55 +05:00
Steven Masley c3c059fbc4 chore: fix provisioner scripts shebang for nix users (#21066) 2025-12-02 13:03:21 -06:00
Mathias Fredriksson ff46917e62 feat: add retention config for workspace_agent_logs (#21039)
Replace hardcoded 7-day retention for workspace agent logs with
configurable retention from deployment settings. Defaults to 7d to
preserve existing behavior.

Depends on #21038
Updates #20743
2025-12-02 16:01:33 +00:00
Mathias Fredriksson d9888ced11 docs: add data retention documentation (#21038)
Document configurable retention policies for Audit Logs, Connection Logs,
and API keys. Add new data-retention.md page and update existing docs to
reference it.

Depends on #21021
Updates #20743
2025-12-02 15:47:36 +00:00
Mathias Fredriksson 9ec90cf2e7 feat(coderd/database/dbpurge): make API keys retention configurable (#21037)
Replace hardcoded 7-day retention for expired API keys with configurable
retention from deployment settings. Skips deletion entirely when effective
retention is 0.

Depends on #21021
Updates #20743
2025-12-02 15:41:38 +00:00
Mathias Fredriksson 929db243cb test(agent/agentcontainers): fix data race and flake in DuringUpWithContainerID test (#21059)
Fixes coder/internal#1169
2025-12-02 16:18:07 +01:00
Mathias Fredriksson c85d79bcdb feat(coderd/database/dbpurge): add retention for audit logs (#21025)
Add configurable retention policy for audit logs. The DeleteOldAuditLogs
query excludes deprecated connection events (connect, disconnect, open,
close) which are handled separately by DeleteOldAuditLogConnectionEvents.

Disabled (0) by default.

Depends on #21021
Updates #20743
2025-12-02 16:50:09 +02:00
Mathias Fredriksson fa7bbe2f55 docs: fix typo in CLAUDE.md (#21058) 2025-12-02 16:35:43 +02:00
Mathias Fredriksson 4e2af837b7 docs(CLAUDE): fix gitignored file loading (#21056)
Follow-up for #21043
2025-12-03 01:21:37 +11:00
Mathias Fredriksson 9ebcca5b0d feat(coderd/database/dbpurge): add retention for connection logs (#21022)
Add `DeleteOldConnectionLogs` query and integrate it into the `dbpurge`
routine. Retention is controlled by `--retention-connection-logs` flag.
Disabled (0) by default.

Depends on #21021
Updates #20743
2025-12-02 14:17:52 +00:00
Mathias Fredriksson 56e7858570 feat(coderd): add retention policy configuration (#21021)
Add `RetentionConfig` with server flags for configuring data retention:

- `--audit-logs-retention`: retention for audit log entries
- `--connection-logs-retention`: retention for connection logs
- `--api-keys-retention`: retention for expired API keys (default 7d)

Updates #20743
2025-12-02 16:04:06 +02:00
Mathias Fredriksson 74d0c39cb3 fix(agent/agentcontainer): allow lifecycle script error on devcontainer up (#21020)
When devcontainer up fails due to a lifecycle script error like
postCreateCommand, the CLI still returns a container ID. Previously
this was discarded and the devcontainer marked as failed. Now we
continue with agent injection if a container ID is available,
allowing users to debug the issue in the running container.

Fixes coder/internal#1137
2025-12-02 15:33:01 +02:00
Ethan bf40d678ec fix(cli): close prebuild runner prometheus server last (#21053)
## Description

Fixes the prebuilds scaletest command where the prometheus server was
being shut down before waiting for metrics to be scraped.

The issue was the defer order - since defers execute in LIFO (last-in,
first-out) order:

**Before (broken):**
1. Register tracing defer (includes wait for prometheus scrape)
2. Register prometheus server defer

Execution order: prometheus closes first, then wait happens (server
already gone!)

**After (fixed):**
1. Register prometheus server defer  
2. Register tracing defer (includes wait for prometheus scrape)

Execution order: wait happens first (server still up), then prometheus
closes.

This matches the pattern used in other scaletest commands.

## Impact

The `coderd_scaletest_prebuild_deletion_jobs_completed` metric (and
potentially others) was always showing 0 because the server shut down
before Prometheus could scrape the final values.

_This PR was generated by [`mux`](https://github.com/coder/mux) and
reviewed by a human._
2025-12-02 12:10:50 +00:00
Mathias Fredriksson a47b3a4cb5 docs: add support for AGENTS.local.md overrides (#21043)
Adds support for local, gitignored `AGENTS.local.md` for
environment-specific overrides.
2025-12-02 10:31:06 +02:00
Ethan 645da33767 test: fix TestDescCacheTimestampUpdate flake (#20975)
## Problem

`TestDescCacheTimestampUpdate` was flaky on Windows CI because
`time.Now()` has ~15.6ms resolution, causing consecutive calls to return
identical timestamps.

## Solution

Inject `quartz.Clock` into `MetricsAggregator` using an options pattern,
making the test deterministic by using a mock clock with explicit time
advancement.

### Changes
- Add `clock quartz.Clock` field to `MetricsAggregator` struct
- Add `WithClock()` option for dependency injection
- Replace all `time.Now()` calls with `ma.clock.Now()`
- Update test to use mock clock with `mClock.Advance(time.Second)`

---

This PR was fully generated by [`mux`](https://github.com/coder/mux)
using Claude Opus 4.5, and reviewed by me.

Closes https://github.com/coder/internal/issues/1146
2025-12-02 10:53:36 +11:00
Jake Howell ab4366f5c6 feat!: implement AI Bridge heading to /deployment/observability (#20791)
> [!CAUTION]
> In whichever release this lands, we've removed the ability to provide
keys via a YAML file (specifically on `openai_key`, `anthropic_key`,
`bedrock_access_key` and finally `bedrock_access_key_secret`). This will
need to be described in the release notes as to not break peoples AI
Bridge integrations upgrading from older versions.

This pull-request ensures that we can see the overview of the settings
of the `AI Bridge` feature within the `/deployment/observability` route.
This set of options only render when the `aibridge` feature flag is
enabled.

### Preview


![preview-ai-bridge-observability](https://github.com/user-attachments/assets/262d2456-94b4-49b2-9b4e-b14583e70ede)
2025-12-01 21:23:46 +00:00
david-fraley afbe9ea154 docs: add GitHub to Coder Task Workflow Guide (#20928)
Co-authored-by: Danielle Maywood <danielle@themaywoods.com>
2025-12-01 13:58:51 -06:00
dependabot[bot] cf6bb40cf8 chore: bump @storybook/react-vite from 9.1.2 to 9.1.16 in /site (#21036)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps
[@storybook/react-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/react-vite)
from 9.1.2 to 9.1.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases"><code>@​storybook/react-vite</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v9.1.16</h2>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add `experimental_devServer` preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.15</h2>
<h2>9.1.15</h2>
<ul>
<li>Core: Add `preview-first-load` telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update `vite-plugin-storybook-nextjs` - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.14</h2>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix `play-fn` tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.12</h2>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.11</h2>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix `sb.mock` usage in Storybook's deployed in subpaths -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.10</h2>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.9</h2>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>v9.1.8</h2>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md"><code>@​storybook/react-vite</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add <code>experimental_devServer</code> preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.15</h2>
<ul>
<li>Core: Add <code>preview-first-load</code> telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix <code>play-fn</code> tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.13</h2>
<ul>
<li>Nextjs: Fix config access for Vite - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32759">#32759</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
</ul>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix <code>sb.mock</code> usage in Storybook's deployed in
subpaths - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.7</h2>
<ul>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> to
2.0.7 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32331">#32331</a>,
thanks <a href="https://github.com/k35o"><code>@​k35o</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/storybookjs/storybook/commit/a54a04cef3ea631f2dacf3631f7f78e4453cd096"><code>a54a04c</code></a>
Bump version from &quot;9.1.15&quot; to &quot;9.1.16&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/d0d17d96288be91ae0969803cbfcd7849b9c98f8"><code>d0d17d9</code></a>
Bump version from &quot;9.1.14&quot; to &quot;9.1.15&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5afb39f85e981d380fba4658a82fac24fa5ce51b"><code>5afb39f</code></a>
Bump version from &quot;9.1.13&quot; to &quot;9.1.14&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/c2483f0e584fea0a7b4c306489b506f6165dc73b"><code>c2483f0</code></a>
Bump version from &quot;9.1.12&quot; to &quot;9.1.13&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/efe8a7ce5bf67cdef96bb4f34a787ef0d6152745"><code>efe8a7c</code></a>
Bump version from &quot;9.1.11&quot; to &quot;9.1.12&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5b2e0edf9f1b56a4708721578be83d439ebc59f5"><code>5b2e0ed</code></a>
Bump version from &quot;9.1.10&quot; to &quot;9.1.11&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/642f0cf47ed9463cecd67fdbad978113edc88196"><code>642f0cf</code></a>
Bump version from &quot;9.1.9&quot; to &quot;9.1.10&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/01867d0d587fe23765bbd43397d861a6e08223f8"><code>01867d0</code></a>
Bump version from &quot;9.1.8&quot; to &quot;9.1.9&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/28833d41b8d0e33bdc11244907fa8d14c8ddd1bf"><code>28833d4</code></a>
Bump version from &quot;9.1.7&quot; to &quot;9.1.8&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/006b304feb4cb0d2fd1408505ebeb5aababb0aad"><code>006b304</code></a>
Bump version from &quot;9.1.6&quot; to &quot;9.1.7&quot; [skip ci]</li>
<li>Additional commits viewable in <a
href="https://github.com/storybookjs/storybook/commits/v9.1.16/code/frameworks/react-vite">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​storybook/react-vite</code> since
your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@storybook/react-vite&package-manager=npm_and_yarn&previous-version=9.1.2&new-version=9.1.16)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:19:39 +00:00
dependabot[bot] 60ac382ae6 chore: bump @storybook/addon-links from 9.1.2 to 9.1.16 in /site (#21035)
Bumps
[@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links)
from 9.1.2 to 9.1.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases"><code>@​storybook/addon-links</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v9.1.16</h2>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add `experimental_devServer` preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.15</h2>
<h2>9.1.15</h2>
<ul>
<li>Core: Add `preview-first-load` telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update `vite-plugin-storybook-nextjs` - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.14</h2>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix `play-fn` tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.12</h2>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.11</h2>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix `sb.mock` usage in Storybook's deployed in subpaths -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.10</h2>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.9</h2>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>v9.1.8</h2>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md"><code>@​storybook/addon-links</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add <code>experimental_devServer</code> preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.15</h2>
<ul>
<li>Core: Add <code>preview-first-load</code> telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix <code>play-fn</code> tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.13</h2>
<ul>
<li>Nextjs: Fix config access for Vite - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32759">#32759</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
</ul>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix <code>sb.mock</code> usage in Storybook's deployed in
subpaths - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.7</h2>
<ul>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> to
2.0.7 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32331">#32331</a>,
thanks <a href="https://github.com/k35o"><code>@​k35o</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/storybookjs/storybook/commit/a54a04cef3ea631f2dacf3631f7f78e4453cd096"><code>a54a04c</code></a>
Bump version from &quot;9.1.15&quot; to &quot;9.1.16&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/d0d17d96288be91ae0969803cbfcd7849b9c98f8"><code>d0d17d9</code></a>
Bump version from &quot;9.1.14&quot; to &quot;9.1.15&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5afb39f85e981d380fba4658a82fac24fa5ce51b"><code>5afb39f</code></a>
Bump version from &quot;9.1.13&quot; to &quot;9.1.14&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/c2483f0e584fea0a7b4c306489b506f6165dc73b"><code>c2483f0</code></a>
Bump version from &quot;9.1.12&quot; to &quot;9.1.13&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/efe8a7ce5bf67cdef96bb4f34a787ef0d6152745"><code>efe8a7c</code></a>
Bump version from &quot;9.1.11&quot; to &quot;9.1.12&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5b2e0edf9f1b56a4708721578be83d439ebc59f5"><code>5b2e0ed</code></a>
Bump version from &quot;9.1.10&quot; to &quot;9.1.11&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/642f0cf47ed9463cecd67fdbad978113edc88196"><code>642f0cf</code></a>
Bump version from &quot;9.1.9&quot; to &quot;9.1.10&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/01867d0d587fe23765bbd43397d861a6e08223f8"><code>01867d0</code></a>
Bump version from &quot;9.1.8&quot; to &quot;9.1.9&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/28833d41b8d0e33bdc11244907fa8d14c8ddd1bf"><code>28833d4</code></a>
Bump version from &quot;9.1.7&quot; to &quot;9.1.8&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/006b304feb4cb0d2fd1408505ebeb5aababb0aad"><code>006b304</code></a>
Bump version from &quot;9.1.6&quot; to &quot;9.1.7&quot; [skip ci]</li>
<li>Additional commits viewable in <a
href="https://github.com/storybookjs/storybook/commits/v9.1.16/code/addons/links">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​storybook/addon-links</code> since
your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@storybook/addon-links&package-manager=npm_and_yarn&previous-version=9.1.2&new-version=9.1.16)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:19:17 +00:00
dependabot[bot] dcb4251849 chore: bump dayjs from 1.11.18 to 1.11.19 in /site (#21033)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps [dayjs](https://github.com/iamkun/dayjs) from 1.11.18 to 1.11.19.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/iamkun/dayjs/releases">dayjs's
releases</a>.</em></p>
<blockquote>
<h2>v1.11.19</h2>
<h2><a
href="https://github.com/iamkun/dayjs/compare/v1.11.18...v1.11.19">1.11.19</a>
(2025-10-31)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>added usage warnings for diff + updated unit tests (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2948">#2948</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/269a7a9cf3649b7a4b328e771173701764a8480d">269a7a9</a>)</li>
<li>dont instantiate regexes within ar locale functions to avoid
performance overhead (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2898">#2898</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/af5e9f0e7649cbd1ecf707daab8303f2733f2563">af5e9f0</a>)</li>
<li>replace italian locale &quot;un' ora fa&quot; with &quot;un'ora
fa&quot;, add tests for it (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2930">#2930</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/9e9f76cf117fa834260b30193434bc4481b4b6be">9e9f76c</a>)</li>
<li>Updated Belarusian locale with relative time (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2656">#2656</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/1d8746c23bd667bde80ee627a915301ebd69e1a2">1d8746c</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/iamkun/dayjs/blob/dev/CHANGELOG.md">dayjs's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/iamkun/dayjs/compare/v1.11.18...v1.11.19">1.11.19</a>
(2025-10-31)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>added usage warnings for diff + updated unit tests (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2948">#2948</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/269a7a9cf3649b7a4b328e771173701764a8480d">269a7a9</a>)</li>
<li>dont instantiate regexes within ar locale functions to avoid
performance overhead (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2898">#2898</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/af5e9f0e7649cbd1ecf707daab8303f2733f2563">af5e9f0</a>)</li>
<li>replace italian locale &quot;un' ora fa&quot; with &quot;un'ora
fa&quot;, add tests for it (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2930">#2930</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/9e9f76cf117fa834260b30193434bc4481b4b6be">9e9f76c</a>)</li>
<li>Updated Belarusian locale with relative time (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2656">#2656</a>)
(<a
href="https://github.com/iamkun/dayjs/commit/1d8746c23bd667bde80ee627a915301ebd69e1a2">1d8746c</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/iamkun/dayjs/commit/02b7a5c6c9500ad1a0d95a894ccc1e9f0942d222"><code>02b7a5c</code></a>
chore(release): 1.11.19 [skip ci]</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/37193be1dff17ecc4debc0cc03e8715cc9c9f1a3"><code>37193be</code></a>
Merge pull request <a
href="https://redirect.github.com/iamkun/dayjs/issues/2950">#2950</a>
from iamkun/dev</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/2db920bf9646b2eb55b56d328c376b5ee6a6fe5d"><code>2db920b</code></a>
chore: update doc</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/4f72974ab53890a50f52348cf3a97595941315a0"><code>4f72974</code></a>
chore: update doc</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/0b36a0711ffb0f488cfdfb73b56ed10d88ec3a32"><code>0b36a07</code></a>
chore: update doc</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/269a7a9cf3649b7a4b328e771173701764a8480d"><code>269a7a9</code></a>
fix: added usage warnings for diff + updated unit tests (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2948">#2948</a>)</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/9e3132e952ca0fbd3c38de3ef8bc9a5e24d235a4"><code>9e3132e</code></a>
chore: update doc</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/84201e609157283e008cc01211777fc82ecfdbd6"><code>84201e6</code></a>
chore: update doc</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/80401e3ff91cc6c5310e6603a4d7a5fa92ca90ec"><code>80401e3</code></a>
chore: update readme</li>
<li><a
href="https://github.com/iamkun/dayjs/commit/88ad3fd5b56291ca3be48400f65f5f8316403c83"><code>88ad3fd</code></a>
test: Add unit test for Belarusian locale (<a
href="https://redirect.github.com/iamkun/dayjs/issues/2934">#2934</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/iamkun/dayjs/compare/v1.11.18...v1.11.19">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dayjs&package-manager=npm_and_yarn&previous-version=1.11.18&new-version=1.11.19)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:18:41 +00:00
dependabot[bot] dc3b11e545 chore: bump yup from 1.6.1 to 1.7.1 in /site (#21032)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps [yup](https://github.com/jquense/yup) from 1.6.1 to 1.7.1.
<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.7.0...v1.7.1">1.7.1</a>
(2025-09-21)</h2>
<h1><a
href="https://github.com/jquense/yup/compare/v1.6.1...v1.7.0">1.7.0</a>
(2025-08-01)</h1>
<h3>Features</h3>
<ul>
<li>Implement standard schema interface (<a
href="https://redirect.github.com/jquense/yup/issues/2258">#2258</a>)
(<a
href="https://github.com/jquense/yup/commit/ced5f514a6033a96f5de3b4ae9c17fe0de86d68f">ced5f51</a>)</li>
<li>resolve ref params if present when describing (<a
href="https://github.com/jquense/yup/commit/ef5303025c38e6e0dc0de53c990e7277cc74164e">ef53030</a>),
closes <a
href="https://redirect.github.com/jquense/yup/issues/2276">#2276</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/jquense/yup/commits">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.6.1&new-version=1.7.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:18:12 +00:00
dependabot[bot] a110c98040 chore: bump lucide-react from 0.552.0 to 0.555.0 in /site (#21031)
Bumps
[lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react)
from 0.552.0 to 0.555.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lucide-icons/lucide/releases">lucide-react's
releases</a>.</em></p>
<blockquote>
<h2>Version 0.555.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(icons): changed <code>calendars</code> icon by <a
href="https://github.com/jguddas"><code>@​jguddas</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3795">lucide-icons/lucide#3795</a></li>
<li>fix(docs): correct package name and description for Flutter and
Lustre package (<a
href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/3701">#3701</a>)
by <a
href="https://github.com/epifaniofrancisco"><code>@​epifaniofrancisco</code></a>
in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3703">lucide-icons/lucide#3703</a></li>
<li>feat(angular): Angular V21 Support by <a
href="https://github.com/JeevanMahesha"><code>@​JeevanMahesha</code></a>
in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3807">lucide-icons/lucide#3807</a></li>
<li>chore(metadata): Adjust navigation category by <a
href="https://github.com/ericfennis"><code>@​ericfennis</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3461">lucide-icons/lucide#3461</a></li>
<li>feat(icons): Add <code>waves-arrow-up</code> and
<code>waves-arrow-down</code> by <a
href="https://github.com/ericfennis"><code>@​ericfennis</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3463">lucide-icons/lucide#3463</a></li>
<li>fix(icons): changed <code>scale</code> icon by <a
href="https://github.com/jamiemlaw"><code>@​jamiemlaw</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3800">lucide-icons/lucide#3800</a></li>
<li>feat(icons): added <code>form</code> icon by <a
href="https://github.com/jguddas"><code>@​jguddas</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3558">lucide-icons/lucide#3558</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lucide-icons/lucide/compare/0.554.0...0.555.0">https://github.com/lucide-icons/lucide/compare/0.554.0...0.555.0</a></p>
<h2>Version 0.554.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(icons): Rename fingerprint icon to fingerprint-pattern by <a
href="https://github.com/ericfennis"><code>@​ericfennis</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3767">lucide-icons/lucide#3767</a></li>
<li>feat(docs): added lucide-rails third-party package by <a
href="https://github.com/theiereman"><code>@​theiereman</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3769">lucide-icons/lucide#3769</a></li>
<li>fix(icons): changed <code>ampersand</code> icon by <a
href="https://github.com/jguddas"><code>@​jguddas</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3771">lucide-icons/lucide#3771</a></li>
<li>fix(icons): changed <code>folder-git-2</code> icon by <a
href="https://github.com/jguddas"><code>@​jguddas</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3790">lucide-icons/lucide#3790</a></li>
<li>fix(icons): update <code>anchor</code> icon by <a
href="https://github.com/jamiemlaw"><code>@​jamiemlaw</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/2523">lucide-icons/lucide#2523</a></li>
<li>feat(icons): added <code>calendars</code> icon by <a
href="https://github.com/jguddas"><code>@​jguddas</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3788">lucide-icons/lucide#3788</a></li>
</ul>
<h2>Breaking change</h2>
<p>For <code>lucide-react</code> and <code>lucide-solid</code>, imports
for <code>Fingerprint</code> icon are changed to
<code>FingerprintPattern</code>.</p>
<h3>Lucide React</h3>
<pre lang="diff"><code>- import { Fingerprint } from
&quot;lucide-react&quot;;
+ import { FingerprintPattern } from &quot;lucide-react&quot;;
</code></pre>
<h3>Lucide Solid</h3>
<pre lang="diff"><code>- import { Fingerprint } from
&quot;lucide/solid&quot;;
+ import { FingerprintPattern } from &quot;lucide/solid&quot;;
<p>// Or</p>
<ul>
<li>import Fingerprint from
&quot;lucide/solid/icons/fingerprint&quot;;</li>
</ul>
<ul>
<li>import FingerprintPattern from
&quot;lucide/solid/icons/fingerprint-pattern&quot;;<br />
</code></pre></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/theiereman"><code>@​theiereman</code></a> made
their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3769">lucide-icons/lucide#3769</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lucide-icons/lucide/compare/0.553.0...0.554.0">https://github.com/lucide-icons/lucide/compare/0.553.0...0.554.0</a></p>
<h2>Version 0.553.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat(icons): added <code>mouse-pointer-2-off</code> icon by <a
href="https://github.com/domingasp"><code>@​domingasp</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3570">lucide-icons/lucide#3570</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/lucide-icons/lucide/commit/80d6f737e0a02c3c11af8d87cb986e33a4ef08d8"><code>80d6f73</code></a>
fix(icons): Rename fingerprint icon to fingerprint-pattern (<a
href="https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react/issues/3767">#3767</a>)</li>
<li>See full diff in <a
href="https://github.com/lucide-icons/lucide/commits/0.555.0/packages/lucide-react">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=lucide-react&package-manager=npm_and_yarn&previous-version=0.552.0&new-version=0.555.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:17:22 +00:00
dependabot[bot] bbf3f763fd chore: bump knip from 5.66.4 to 5.71.0 in /site (#21029)
Bumps [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip)
from 5.66.4 to 5.71.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/webpro-nl/knip/releases">knip's
releases</a>.</em></p>
<blockquote>
<h2>Release 5.71.0</h2>
<ul>
<li>Add <code>sed</code> to globally ignored binaries (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1365">#1365</a>)
(ea8d61899fe8d4ba160ec998d564d3c9f5aafd55) - thanks <a
href="https://github.com/jmoses"><code>@​jmoses</code></a>!</li>
<li>Consider NS in condition referenced (closes <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1364">#1364</a>)
(7a5a8ea2351b31e1cefb1405d33b8dbb464c2ec9)</li>
<li>Improve dynamic import binding handling (close <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1368">#1368</a>)
(b210b18c18357885b33827fc23a7333615ef7d64)</li>
<li>Introduce graph explorer
(b107af4cfbf034159903cf79c82e6926ff7dd91c)</li>
<li>Find mdx plugins in next config (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1367">#1367</a>)
(07c0539dd167681e2f5533bef15a7759bd6a3f5f)</li>
<li>Filter out subshell function calls (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1369">#1369</a>)
(97d8f6acc9fda00486b2072f9717789d54b4e225)</li>
</ul>
<h2>Release 5.70.2</h2>
<ul>
<li>Restore &amp; add TS v5.5.0 workarounds ↻ oh my
(fe7ea23981ae1c94118041299b9f1fecceba62d4)</li>
<li>Extend &amp; refactor <code>Import</code> in module graph
(ad25794fc5ed465cf4be151df05fc4196d1589e4)</li>
<li>Fix <code>TYPE_ONLY</code> instance
(b431303d60f84f6abf77f37f93ccf9ab399d4cc9)</li>
<li>Add side-effect imports as well
(ed289ba9e69a030f945a42aef0828029fbe9b734)</li>
<li>Remove <code>project</code> patterns from astro plugin
(ac9e378d2bdf84b70791bdce9febc511bee924b4)</li>
<li>Don't leak negated entry into project patterns
(eab2b892c774c8ed545952997e66cf53719fa68e)</li>
<li>Run glob sets with negations separately (resolves <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1249">#1249</a>)
(969e3afdb25d9e607ff68f60543c8f1e64be5a69)</li>
<li>Include all groups to negate entry patterns in production mode
(406592dca0e44917703b24cee78c2d85b0a42fb6)</li>
</ul>
<h2>Release 5.70.1</h2>
<ul>
<li>chore: fix vitest node env recognition (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1360">#1360</a>)
(9a38e10230b18b256ee8ed03dcc5217029b5298d) - thanks <a
href="https://github.com/jonathansamines"><code>@​jonathansamines</code></a>!</li>
<li>Improve some export/import positions
(f6f58fa96ef1243c4e5c70e8860b286bd63bed94)</li>
<li>Add some common hints/FAQs to plugin test template
(da7cf84a501321a9bbb3e118e840d36d47abad56)</li>
</ul>
<h2>Release 5.70.0</h2>
<ul>
<li>Revert &quot;Revive some tests in Bun&quot;
(f1406b5d8fc5add850e88ea23619bad745519c97)</li>
<li>feat(plugins): Add Prisma plugin entry and Prisma schema compiler
(<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1340">#1340</a>)
(9f80aa4b09f9c9c5a0e55015a8b0eae9fb2e1812) - thanks <a
href="https://github.com/CHC383"><code>@​CHC383</code></a>!</li>
<li>Improve some export/import positions
(b19282b3ff84d1486820afb9f09e1384d8934bc8)</li>
<li>Move block to group top-level patterns
(bba25f33d489fb1942925d022348536513e4a4dd)</li>
<li>Improve some naming around module graph
(63d61176f0613bb405627f6cab2dc1bbee052df5)</li>
<li>Minor refactors (a63b0dce0f886f297650185c72003f7c935a9deb)</li>
<li>Update auto-fix.mdx (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1356">#1356</a>)
(c64d9056ef9aed63b1b8255dc1bad120a21f311f) - thanks <a
href="https://github.com/skvale"><code>@​skvale</code></a>!</li>
<li>Improve side-effects &amp; opaque import call handling (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1352">#1352</a>)
(e364589d790ce185c9a3b29aa2ea00f2663064d6)</li>
<li>Add some unit tests for <code>isIdentifierReferenced</code>
(f31eab4b443f084ff4af3eab187c352deab27089)</li>
<li>Add support for awaited import call promise
(92cbcef6b0501891e9e62ef6a3ef801b0de945e7)</li>
<li>Edit and dim tag hints title
(e4affd2f0651ba530817bb04805805e6474b0fbe)</li>
<li>feat(plugins): Add taskfile plugin (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1357">#1357</a>)
(f64b72c31f0ee47da68a1eff96505dc770c43194) - thanks <a
href="https://github.com/elierotenberg"><code>@​elierotenberg</code></a>!</li>
<li>Improve pragmas handling/setup (resolves <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1358">#1358</a>)
(e0f497cc937e5cb5281a84a7e9c2181942b94361)</li>
<li>Upgrade js-yaml + some others (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1359">#1359</a>)
(5195888a691c200c971e214f28ad20bf4a395862)</li>
<li>Clean up (da9440fb6a09222cc8a50093178e6cd69fee3bd6)</li>
</ul>
<h2>Release 5.69.1</h2>
<ul>
<li>Release <code>@​knip/create-config</code> 1.0.8
(87405169656dbfa8cf931092d516c91647f95529)</li>
<li>Edit docs (5eb8a6943904505b5630dee1ee58379c7707f72d)</li>
<li>Apply Next.js page extensions to app directory (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1351">#1351</a>)
(f9cf9dc0fd44880a515979a104261ed77fa8878d) - thanks <a
href="https://github.com/remcohaszing"><code>@​remcohaszing</code></a>!</li>
<li>Refactor fixes &amp; consistently use <code>issue.fixes</code>
(d7b45cfebb135881160ecda2acf0ad5239d98441)</li>
<li>Revive some tests in Bun
(74a0bd8ebf6e68e121333489495d2b6d58545fd4)</li>
<li>Fix import identifier/specifier pos
(95d2c04d5400ffb57f9057653c0977967b3ae02e)</li>
<li>Fix namespace import pos
(6b6b80b813d545d16ba74fc68beecd492f1252a2)</li>
<li>Improve some export/import positions
(9b87b1ac20fb33d9f9b5af1de1cbe1d053fa18ff)</li>
<li>Rely on absolute paths with formatly (npx acts weird)
(6653f357074c559f537af1b5563b191372d7901e)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/webpro-nl/knip/commit/879a42ca09721292fc3443443d8d5f9df96c9aa7"><code>879a42c</code></a>
Release 5.71.0</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/97d8f6acc9fda00486b2072f9717789d54b4e225"><code>97d8f6a</code></a>
Filter out subshell function calls (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1369">#1369</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/07c0539dd167681e2f5533bef15a7759bd6a3f5f"><code>07c0539</code></a>
Find mdx plugins in next config (resolve <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1367">#1367</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/b107af4cfbf034159903cf79c82e6926ff7dd91c"><code>b107af4</code></a>
Introduce graph explorer</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/b210b18c18357885b33827fc23a7333615ef7d64"><code>b210b18</code></a>
Improve dynamic import binding handling (close <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1368">#1368</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/7a5a8ea2351b31e1cefb1405d33b8dbb464c2ec9"><code>7a5a8ea</code></a>
Consider NS in condition referenced (closes <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1364">#1364</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/ea8d61899fe8d4ba160ec998d564d3c9f5aafd55"><code>ea8d618</code></a>
Add <code>sed</code> to globally ignored binaries (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1365">#1365</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/59abdaa9c40bc750d18c5bfb3ddc0f44def93b30"><code>59abdaa</code></a>
Release 5.70.2</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/406592dca0e44917703b24cee78c2d85b0a42fb6"><code>406592d</code></a>
Include all groups to negate entry patterns in production mode</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/969e3afdb25d9e607ff68f60543c8f1e64be5a69"><code>969e3af</code></a>
Run glob sets with negations separately (resolves <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1249">#1249</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/webpro-nl/knip/commits/5.71.0/packages/knip">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=knip&package-manager=npm_and_yarn&previous-version=5.66.4&new-version=5.71.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:17:00 +00:00
dependabot[bot] 59866d9f52 chore: bump autoprefixer from 10.4.21 to 10.4.22 in /site (#21030)
Bumps [autoprefixer](https://github.com/postcss/autoprefixer) from
10.4.21 to 10.4.22.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/autoprefixer/releases">autoprefixer's
releases</a>.</em></p>
<blockquote>
<h2>10.4.22</h2>
<ul>
<li>Fixed <code>stretch</code> prefixes on new Can I Use database.</li>
<li>Updated <code>fraction.js</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/postcss/autoprefixer/blob/main/CHANGELOG.md">autoprefixer's
changelog</a>.</em></p>
<blockquote>
<h2>10.4.22</h2>
<ul>
<li>Fixed <code>stretch</code> prefixes on new Can I Use database.</li>
<li>Updated <code>fraction.js</code>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/postcss/autoprefixer/commit/73dc62c779bf51f2883f9541dc62fd164262e872"><code>73dc62c</code></a>
Release 10.4.22 version</li>
<li><a
href="https://github.com/postcss/autoprefixer/commit/9973c59f4880abff46c94fd5554e7e4ea194b549"><code>9973c59</code></a>
Lock CI action versions</li>
<li><a
href="https://github.com/postcss/autoprefixer/commit/4b4feca71abf7596d978fe7a1e048dec1608d740"><code>4b4feca</code></a>
Fix Node.js 10 on CI</li>
<li><a
href="https://github.com/postcss/autoprefixer/commit/15c21d3a7c626ec8269fdb926ed76e729593f09e"><code>15c21d3</code></a>
Fix old Node.js CI</li>
<li><a
href="https://github.com/postcss/autoprefixer/commit/27523c1c560933adfb5f8e29184a85b45ed60c87"><code>27523c1</code></a>
Update fraction.js</li>
<li><a
href="https://github.com/postcss/autoprefixer/commit/88a0d3e0f8034eb9a54087c74a36abb771de41a0"><code>88a0d3e</code></a>
Update dependencies and fix stretch and update example</li>
<li>See full diff in <a
href="https://github.com/postcss/autoprefixer/compare/10.4.21...10.4.22">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=autoprefixer&package-manager=npm_and_yarn&previous-version=10.4.21&new-version=10.4.22)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:16:55 +00:00
dependabot[bot] e00578cf99 chore: bump axios from 1.13.1 to 1.13.2 in /site (#21028)
Bumps [axios](https://github.com/axios/axios) from 1.13.1 to 1.13.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/releases">axios's
releases</a>.</em></p>
<blockquote>
<h2>Release v1.13.2</h2>
<h2>Release notes:</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>http:</strong> fix 'socket hang up' bug for keep-alive
requests when using timeouts; (<a
href="https://redirect.github.com/axios/axios/issues/7206">#7206</a>)
(<a
href="https://github.com/axios/axios/commit/8d372335f5c50ecd01e8615f2468a9eb19703117">8d37233</a>)</li>
<li><strong>http:</strong> use default export for http2 module to
support stubs; (<a
href="https://redirect.github.com/axios/axios/issues/7196">#7196</a>)
(<a
href="https://github.com/axios/axios/commit/0588880ac7ddba7594ef179930493884b7e90bf5">0588880</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>http:</strong> fix early loop exit; (<a
href="https://redirect.github.com/axios/axios/issues/7202">#7202</a>)
(<a
href="https://github.com/axios/axios/commit/12c314b603e7852a157e93e47edb626a471ba6c5">12c314b</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+28/-9
([#7206](https://github.com/axios/axios/issues/7206)
[#7202](https://github.com/axios/axios/issues/7202) )">Dmitriy
Mozgovoy</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/kasperisager"
title="+9/-9 ([#7196](https://github.com/axios/axios/issues/7196)
)">Kasper Isager Dalsgarð</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/blob/v1.x/CHANGELOG.md">axios's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/axios/axios/compare/v1.13.1...v1.13.2">1.13.2</a>
(2025-11-04)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>http:</strong> fix 'socket hang up' bug for keep-alive
requests when using timeouts; (<a
href="https://redirect.github.com/axios/axios/issues/7206">#7206</a>)
(<a
href="https://github.com/axios/axios/commit/8d372335f5c50ecd01e8615f2468a9eb19703117">8d37233</a>)</li>
<li><strong>http:</strong> use default export for http2 module to
support stubs; (<a
href="https://redirect.github.com/axios/axios/issues/7196">#7196</a>)
(<a
href="https://github.com/axios/axios/commit/0588880ac7ddba7594ef179930493884b7e90bf5">0588880</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>http:</strong> fix early loop exit; (<a
href="https://redirect.github.com/axios/axios/issues/7202">#7202</a>)
(<a
href="https://github.com/axios/axios/commit/12c314b603e7852a157e93e47edb626a471ba6c5">12c314b</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+28/-9
([#7206](https://github.com/axios/axios/issues/7206)
[#7202](https://github.com/axios/axios/issues/7202) )">Dmitriy
Mozgovoy</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/kasperisager"
title="+9/-9 ([#7196](https://github.com/axios/axios/issues/7196)
)">Kasper Isager Dalsgarð</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/axios/axios/commit/08b84b52d5835d0c7b81049c365c3d271ade8bff"><code>08b84b5</code></a>
chore(release): v1.13.2 (<a
href="https://redirect.github.com/axios/axios/issues/7207">#7207</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/8d372335f5c50ecd01e8615f2468a9eb19703117"><code>8d37233</code></a>
fix(http): fix 'socket hang up' bug for keep-alive requests when using
timeou...</li>
<li><a
href="https://github.com/axios/axios/commit/12c314b603e7852a157e93e47edb626a471ba6c5"><code>12c314b</code></a>
perf(http): fix early loop exit; (<a
href="https://redirect.github.com/axios/axios/issues/7202">#7202</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/f6d79e773baf70bf4e6d888e72d4bcf589060a84"><code>f6d79e7</code></a>
chore(sponsor): update sponsor block (<a
href="https://redirect.github.com/axios/axios/issues/7203">#7203</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/0588880ac7ddba7594ef179930493884b7e90bf5"><code>0588880</code></a>
fix(http): use default export for http2 module to support stubs; (<a
href="https://redirect.github.com/axios/axios/issues/7196">#7196</a>)</li>
<li>See full diff in <a
href="https://github.com/axios/axios/compare/v1.13.1...v1.13.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=axios&package-manager=npm_and_yarn&previous-version=1.13.1&new-version=1.13.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:16:44 +00:00
dependabot[bot] fe850752dd chore: bump formik from 2.4.6 to 2.4.9 in /site (#21027)
Bumps [formik](https://github.com/jaredpalmer/formik) from 2.4.6 to
2.4.9.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jaredpalmer/formik/releases">formik's
releases</a>.</em></p>
<blockquote>
<h2>formik@2.4.9</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/jaredpalmer/formik/pull/4051">#4051</a>
<a
href="https://github.com/jaredpalmer/formik/commit/8f9d04d206146ca941facf37ddd9ddb459c459dc"><code>8f9d04d</code></a>
Thanks <a
href="https://github.com/Moumouls"><code>@​Moumouls</code></a>! - fix:
jsx ref for react 19</li>
</ul>
<h2>formik@2.4.8</h2>
<h3>Patch Changes</h3>
<ul>
<li><a
href="https://redirect.github.com/jaredpalmer/formik/pull/4042">#4042</a>
<a
href="https://github.com/jaredpalmer/formik/commit/1de45decf8fd70c038fca88dc1a6543aac269553"><code>1de45de</code></a>
Thanks <a
href="https://github.com/apps/copilot-swe-agent"><code>@​copilot-swe-agent</code></a>!
- Replace JSX.IntrinsicElements with React.JSX.IntrinsicElements for
React 19 compatibility. The global JSX namespace was removed in React
19, so we now use React.JSX.IntrinsicElements instead.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jaredpalmer/formik/commit/91475adbf33579561e580eceea0c031f4ec2e992"><code>91475ad</code></a>
Merge pull request <a
href="https://redirect.github.com/jaredpalmer/formik/issues/4053">#4053</a>
from jaredpalmer/changeset-release/main</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/920f107205a9e3440efc5dba127e3aecbe98fda5"><code>920f107</code></a>
Version Packages</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/8f9d04d206146ca941facf37ddd9ddb459c459dc"><code>8f9d04d</code></a>
fix: jsx ref for react 19 (<a
href="https://redirect.github.com/jaredpalmer/formik/issues/4051">#4051</a>)</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/ddfae3fad836c088f376e88c2be5282262429c1c"><code>ddfae3f</code></a>
Merge pull request <a
href="https://redirect.github.com/jaredpalmer/formik/issues/4045">#4045</a>
from jaredpalmer/changeset-release/main</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/741c9d448b13590900bd5170b55cd03ade33f578"><code>741c9d4</code></a>
Version Packages</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/f7f8f53f9ee379d4e2048ee4c73d1bf9c4af48ad"><code>f7f8f53</code></a>
Upgrade changesets/action to v1.5.3 and npm packages (<a
href="https://redirect.github.com/jaredpalmer/formik/issues/4043">#4043</a>)</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/7fca4b2cdc881dc0b79a2f219df57a7e15866fc2"><code>7fca4b2</code></a>
Merge pull request <a
href="https://redirect.github.com/jaredpalmer/formik/issues/4044">#4044</a>
from jaredpalmer/copilot/upgrade-to-latest-turborepo</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/c8e5527ff4c1f2ab9a876f8df71dd24b443f7efe"><code>c8e5527</code></a>
Add .turbo to .gitignore and remove cached files</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/488dbec5dd619ba71814dc9fb643c0da5f65482a"><code>488dbec</code></a>
Upgrade turborepo from 1.9.9 to 2.6.0 with initial configuration
changes</li>
<li><a
href="https://github.com/jaredpalmer/formik/commit/dc03941b8a9d198aad54e624b850c6446eaadaec"><code>dc03941</code></a>
Initial plan</li>
<li>Additional commits viewable in <a
href="https://github.com/jaredpalmer/formik/compare/formik@2.4.6...formik@2.4.9">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=formik&package-manager=npm_and_yarn&previous-version=2.4.6&new-version=2.4.9)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:16:02 +00:00
dependabot[bot] d786bc400c chore: bump react-syntax-highlighter from 15.6.1 to 15.6.6 in /site (#21026)
Bumps
[react-syntax-highlighter](https://github.com/react-syntax-highlighter/react-syntax-highlighter)
from 15.6.1 to 15.6.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/releases">react-syntax-highlighter's
releases</a>.</em></p>
<blockquote>
<h2>v15.6.6</h2>
<p>Updated <code>overrides</code> block attempting to solve transitive
<code>prismjs</code> dependency issue:</p>
<pre><code>&quot;overrides&quot;: {
    &quot;prismjs&quot;: &quot;^1.30.0&quot;,
    &quot;refractor&quot;: {
      &quot;prismjs&quot;: &quot;^1.30.0&quot;
    }
  }
</code></pre>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.5...v15.6.6">https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.5...v15.6.6</a></p>
<h2>v15.6.5</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump elliptic from 6.5.5 to 6.6.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/576">react-syntax-highlighter/react-syntax-highlighter#576</a></li>
<li>Bump ws from 6.2.2 to 6.2.3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/574">react-syntax-highlighter/react-syntax-highlighter#574</a></li>
<li>Bump express from 4.19.2 to 4.21.1 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/572">react-syntax-highlighter/react-syntax-highlighter#572</a></li>
<li>Bump send and express by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/571">react-syntax-highlighter/react-syntax-highlighter#571</a></li>
<li>Bump cookie and express by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/570">react-syntax-highlighter/react-syntax-highlighter#570</a></li>
<li>Bump serve-static and express by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/569">react-syntax-highlighter/react-syntax-highlighter#569</a></li>
<li>Bump body-parser and express by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/568">react-syntax-highlighter/react-syntax-highlighter#568</a></li>
<li>Add Boemly to the built with section of the readme by <a
href="https://github.com/lukasbals"><code>@​lukasbals</code></a> in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/467">react-syntax-highlighter/react-syntax-highlighter#467</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/lukasbals"><code>@​lukasbals</code></a>
made their first contribution in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/467">react-syntax-highlighter/react-syntax-highlighter#467</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.4...v15.6.5">https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.4...v15.6.5</a></p>
<h2>v15.6.4</h2>
<h2>What's Changed</h2>
<ul>
<li>Override <code>refractor 3.6.0</code>'s <code>prismjs</code>
dependency by <a
href="https://github.com/simmerer"><code>@​simmerer</code></a> in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/605">react-syntax-highlighter/react-syntax-highlighter#605</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.3...v15.6.4">https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.3...v15.6.4</a></p>
<h2>v15.6.3</h2>
<h2>What's Changed</h2>
<ul>
<li>fix line count error by <a
href="https://github.com/bbbert"><code>@​bbbert</code></a> in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/583">react-syntax-highlighter/react-syntax-highlighter#583</a></li>
<li>fix spelling error by <a
href="https://github.com/BrianHung"><code>@​BrianHung</code></a> in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/579">react-syntax-highlighter/react-syntax-highlighter#579</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/bbbert"><code>@​bbbert</code></a> made
their first contribution in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/583">react-syntax-highlighter/react-syntax-highlighter#583</a></li>
<li><a href="https://github.com/BrianHung"><code>@​BrianHung</code></a>
made their first contribution in <a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/pull/579">react-syntax-highlighter/react-syntax-highlighter#579</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.2...v15.6.3">https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.2...v15.6.3</a></p>
<h2>v15.6.2</h2>
<h2>What's Changed</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/blob/master/CHANGELOG.MD">react-syntax-highlighter's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/56a1b0f779e3bc0175a6e8915fa9274c0f4ca985"><code>56a1b0f</code></a>
add top-level override for prismjs, bump to 15.6.6</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/a169285045a1448d58102e034ac38df63596745a"><code>a169285</code></a>
bump to 15.6.5</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/5d507f0a97d29d9f74c2ce0844f87a08c85b0a46"><code>5d507f0</code></a>
Add Boemly to the built with section of the readme (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/467">#467</a>)</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/0bda76915b41ec92aea9e79f360476efc1b7fb2c"><code>0bda769</code></a>
Bump body-parser and express (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/568">#568</a>)</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/9fb3f732fc263056e6504fced239dfe0e87dd67a"><code>9fb3f73</code></a>
Bump serve-static and express (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/569">#569</a>)</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/5f0dbfcc3c5ec44460595011def5aaa9821dd560"><code>5f0dbfc</code></a>
Bump cookie and express (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/570">#570</a>)</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/53e66073ca675005ec069b20a16ff38a81d10a5e"><code>53e6607</code></a>
Bump send and express (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/571">#571</a>)</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/130c9c322b7d5975440c0476f6418e2c22a696d6"><code>130c9c3</code></a>
Bump express from 4.19.2 to 4.21.1 (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/572">#572</a>)</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/93825906ee0f0f6671830f3d0da601c8174d52d9"><code>9382590</code></a>
Bump ws from 6.2.2 to 6.2.3 (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/574">#574</a>)</li>
<li><a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/commit/7ecf60606abccc2c7edef5fc254338a7c951db3c"><code>7ecf606</code></a>
Bump elliptic from 6.5.5 to 6.6.0 (<a
href="https://redirect.github.com/react-syntax-highlighter/react-syntax-highlighter/issues/576">#576</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/react-syntax-highlighter/react-syntax-highlighter/compare/v15.6.1...v15.6.6">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react-syntax-highlighter&package-manager=npm_and_yarn&previous-version=15.6.1&new-version=15.6.6)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 15:15:38 +00:00
Jakub Domeracki cbb0952e5a chore: disable autoupgrade of GH Actions version upgrades (#21019)
Addresses
https://github.com/coder/internal/issues/1166
2025-12-01 15:09:36 +01:00
Pedro Magalhães d3fe72c861 chore: add ansible icon (#20887) 2025-12-01 15:43:23 +05:00
dependabot[bot] 163f495346 chore: bump @types/node from 20.17.16 to 20.19.25 in /site (#21003)
Bumps
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
from 20.17.16 to 20.19.25.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/node&package-manager=npm_and_yarn&previous-version=20.17.16&new-version=20.19.25)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 10:33:15 +00:00
dependabot[bot] fad8b54ab8 ci: bump the github-actions group across 1 directory with 6 updates (#21017)
Bumps the github-actions group with 6 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `5.0.0` |
`6.0.0` |
| [crate-ci/typos](https://github.com/crate-ci/typos) | `1.39.2` |
`1.40.0` |
| [chromaui/action](https://github.com/chromaui/action) | `13.3.3` |
`13.3.4` |
| [fluxcd/flux2](https://github.com/fluxcd/flux2) | `2.7.3` | `2.7.5` |
|
[tj-actions/changed-files](https://github.com/tj-actions/changed-files)
| `70069877f29101175ed2b055d210fe8b1d54d7d7` |
`abdd2f68ea150cee8f236d4a9fb4e0f2491abf1b` |
| [github/codeql-action](https://github.com/github/codeql-action) |
`4.31.3` | `4.31.6` |


Updates `actions/checkout` from 5.0.0 to 6.0.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/releases">actions/checkout's
releases</a>.</em></p>
<blockquote>
<h2>v6.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>v6-beta by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2298">actions/checkout#2298</a></li>
<li>update readme/changelog for v6 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2311">actions/checkout#2311</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5.0.0...v6.0.0">https://github.com/actions/checkout/compare/v5.0.0...v6.0.0</a></p>
<h2>v6-beta</h2>
<h2>What's Changed</h2>
<p>Updated persist-credentials to store the credentials under
<code>$RUNNER_TEMP</code> instead of directly in the local git
config.</p>
<p>This requires a minimum Actions Runner version of <a
href="https://github.com/actions/runner/releases/tag/v2.329.0">v2.329.0</a>
to access the persisted credentials for <a
href="https://docs.github.com/en/actions/tutorials/use-containerized-services/create-a-docker-container-action">Docker
container action</a> scenarios.</p>
<h2>v5.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/actions/checkout/compare/v5...v5.0.1">https://github.com/actions/checkout/compare/v5...v5.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>V6.0.0</h2>
<ul>
<li>Persist creds to a separate file by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2286">actions/checkout#2286</a></li>
<li>Update README to include Node.js 24 support details and requirements
by <a href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2248">actions/checkout#2248</a></li>
</ul>
<h2>V5.0.1</h2>
<ul>
<li>Port v6 cleanup to v5 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2301">actions/checkout#2301</a></li>
</ul>
<h2>V5.0.0</h2>
<ul>
<li>Update actions checkout to use node 24 by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2226">actions/checkout#2226</a></li>
</ul>
<h2>V4.3.1</h2>
<ul>
<li>Port v6 cleanup to v4 by <a
href="https://github.com/ericsciple"><code>@​ericsciple</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2305">actions/checkout#2305</a></li>
</ul>
<h2>V4.3.0</h2>
<ul>
<li>docs: update README.md by <a
href="https://github.com/motss"><code>@​motss</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1971">actions/checkout#1971</a></li>
<li>Add internal repos for checking out multiple repositories by <a
href="https://github.com/mouismail"><code>@​mouismail</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1977">actions/checkout#1977</a></li>
<li>Documentation update - add recommended permissions to Readme by <a
href="https://github.com/benwells"><code>@​benwells</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2043">actions/checkout#2043</a></li>
<li>Adjust positioning of user email note and permissions heading by <a
href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2044">actions/checkout#2044</a></li>
<li>Update README.md by <a
href="https://github.com/nebuk89"><code>@​nebuk89</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2194">actions/checkout#2194</a></li>
<li>Update CODEOWNERS for actions by <a
href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/2224">actions/checkout#2224</a></li>
<li>Update package dependencies by <a
href="https://github.com/salmanmkc"><code>@​salmanmkc</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/2236">actions/checkout#2236</a></li>
</ul>
<h2>v4.2.2</h2>
<ul>
<li><code>url-helper.ts</code> now leverages well-known environment
variables by <a href="https://github.com/jww3"><code>@​jww3</code></a>
in <a
href="https://redirect.github.com/actions/checkout/pull/1941">actions/checkout#1941</a></li>
<li>Expand unit test coverage for <code>isGhes</code> by <a
href="https://github.com/jww3"><code>@​jww3</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1946">actions/checkout#1946</a></li>
</ul>
<h2>v4.2.1</h2>
<ul>
<li>Check out other refs/* by commit if provided, fall back to ref by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1924">actions/checkout#1924</a></li>
</ul>
<h2>v4.2.0</h2>
<ul>
<li>Add Ref and Commit outputs by <a
href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkout#1180</a></li>
<li>Dependency updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>- <a
href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkout#1777</a>,
<a
href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkout#1872</a></li>
</ul>
<h2>v4.1.7</h2>
<ul>
<li>Bump the minor-npm-dependencies group across 1 directory with 4
updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkout#1739</a></li>
<li>Bump actions/checkout from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkout#1697</a></li>
<li>Check out other refs/* by commit by <a
href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkout#1774</a></li>
<li>Pin actions/checkout's own workflows to a known, good, stable
version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkout#1776</a></li>
</ul>
<h2>v4.1.6</h2>
<ul>
<li>Check platform to set archive extension appropriately by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkout#1732</a></li>
</ul>
<h2>v4.1.5</h2>
<ul>
<li>Update NPM dependencies by <a
href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in
<a
href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkout#1703</a></li>
<li>Bump github/codeql-action from 2 to 3 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkout#1694</a></li>
<li>Bump actions/setup-node from 1 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkout#1696</a></li>
<li>Bump actions/upload-artifact from 2 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkout#1695</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/actions/checkout/commit/1af3b93b6815bc44a9784bd300feb67ff0d1eeb3"><code>1af3b93</code></a>
update readme/changelog for v6 (<a
href="https://redirect.github.com/actions/checkout/issues/2311">#2311</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/71cf2267d89c5cb81562390fa70a37fa40b1305e"><code>71cf226</code></a>
v6-beta (<a
href="https://redirect.github.com/actions/checkout/issues/2298">#2298</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/069c6959146423d11cd0184e6accf28f9d45f06e"><code>069c695</code></a>
Persist creds to a separate file (<a
href="https://redirect.github.com/actions/checkout/issues/2286">#2286</a>)</li>
<li><a
href="https://github.com/actions/checkout/commit/ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493"><code>ff7abcd</code></a>
Update README to include Node.js 24 support details and requirements (<a
href="https://redirect.github.com/actions/checkout/issues/2248">#2248</a>)</li>
<li>See full diff in <a
href="https://github.com/actions/checkout/compare/08c6903cd8c0fde910a37f88322edcfb5dd907a8...1af3b93b6815bc44a9784bd300feb67ff0d1eeb3">compare
view</a></li>
</ul>
</details>
<br />

Updates `crate-ci/typos` from 1.39.2 to 1.40.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
releases</a>.</em></p>
<blockquote>
<h2>v1.40.0</h2>
<h2>[1.40.0] - 2025-11-26</h2>
<h3>Features</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1405">November
2025</a> changes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
changelog</a>.</em></p>
<blockquote>
<h1>Change Log</h1>
<p>All notable changes to this project will be documented in this
file.</p>
<p>The format is based on <a href="https://keepachangelog.com/">Keep a
Changelog</a>
and this project adheres to <a href="https://semver.org/">Semantic
Versioning</a>.</p>
<!-- raw HTML omitted -->
<h2>[Unreleased] - ReleaseDate</h2>
<h2>[1.40.0] - 2025-11-26</h2>
<h3>Features</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1405">November
2025</a> changes</li>
</ul>
<h2>[1.39.2] - 2025-11-13</h2>
<h3>Fixes</h3>
<ul>
<li>Don't offer <code>entry</code> as a correction for
<code>entrys</code></li>
</ul>
<h2>[1.39.1] - 2025-11-12</h2>
<h3>Features</h3>
<ul>
<li>Make <code>--help</code> more vibrant</li>
</ul>
<h2>[1.39.0] - 2025-10-31</h2>
<h3>Features</h3>
<ul>
<li>Updated the dictionary with the <a
href="https://redirect.github.com/crate-ci/typos/issues/1383">October
2025</a> changes</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>When a typo is pluralized, prefer pluralized corrections</li>
</ul>
<h2>[1.38.1] - 2025-10-07</h2>
<h3>Fixes</h3>
<ul>
<li>Ignore common golang identifiers</li>
</ul>
<h2>[1.38.0] - 2025-10-06</h2>
<h3>Features</h3>
<ul>
<li>Update type list</li>
</ul>
<h3>Fixes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crate-ci/typos/commit/2d0ce569feab1f8752f1dde43cc2f2aa53236e06"><code>2d0ce56</code></a>
chore: Release</li>
<li><a
href="https://github.com/crate-ci/typos/commit/efbd900f8db9952781b6bd1ad83baa38ebd153e3"><code>efbd900</code></a>
chore: Release</li>
<li><a
href="https://github.com/crate-ci/typos/commit/863fd15db8bf16bfe9117ec1a83ea7b6e802e9f3"><code>863fd15</code></a>
docs: Update changelog</li>
<li><a
href="https://github.com/crate-ci/typos/commit/9a27b16791dd73549457a07f247bc4920f787919"><code>9a27b16</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1432">#1432</a>
from epage/nov</li>
<li><a
href="https://github.com/crate-ci/typos/commit/3dbd9d4eacab7f22586ea581e4d403c3ca9dbbb7"><code>3dbd9d4</code></a>
feat(dict): November additions</li>
<li><a
href="https://github.com/crate-ci/typos/commit/a1a16c7b7c25d1c27cc750525aada8b9ae68b716"><code>a1a16c7</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1427">#1427</a>
from deining/bump-github-action</li>
<li><a
href="https://github.com/crate-ci/typos/commit/cb8d2e78ff23c82fca05340ed256b04513d022b9"><code>cb8d2e7</code></a>
docs: Bump GitHub checkout action in 'github-action.md'</li>
<li><a
href="https://github.com/crate-ci/typos/commit/9f99fb8dfe87b8a3441863fb2e5d5da88a2aa9a2"><code>9f99fb8</code></a>
docs(ref): Clarify extend-words / extend-identifiers</li>
<li>See full diff in <a
href="https://github.com/crate-ci/typos/compare/626c4bedb751ce0b7f03262ca97ddda9a076ae1c...2d0ce569feab1f8752f1dde43cc2f2aa53236e06">compare
view</a></li>
</ul>
</details>
<br />

Updates `chromaui/action` from 13.3.3 to 13.3.4
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/chromaui/action/commit/4c20b95e9d3209ecfdf9cd6aace6bbde71ba1694"><code>4c20b95</code></a>
v13.3.4</li>
<li>See full diff in <a
href="https://github.com/chromaui/action/compare/ac86f2ff0a458ffbce7b40698abd44c0fa34d4b6...4c20b95e9d3209ecfdf9cd6aace6bbde71ba1694">compare
view</a></li>
</ul>
</details>
<br />

Updates `fluxcd/flux2` from 2.7.3 to 2.7.5
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/fluxcd/flux2/releases">fluxcd/flux2's
releases</a>.</em></p>
<blockquote>
<h2>v2.7.5</h2>
<h2>Highlights</h2>
<p>Flux v2.7.5 is a patch release that comes with fixes to
helm-controller. Users are encouraged to upgrade for the best
experience.</p>
<p>ℹ️ Please follow the <a
href="https://github.com/fluxcd/flux2/discussions/5572">Upgrade
Procedure for Flux v2.7+</a> for a smooth upgrade from Flux v2.6 to the
latest version.</p>
<p>Fixes:</p>
<ul>
<li>Fix HelmRelease history truncation when using the
<code>RetryOnFailure</code> strategy.</li>
</ul>
<p>⚠️ Note that signature verification for OCI artifacts in
source-controller is not compatible with Cosign v3.
Flux users are advised to use <a
href="https://fluxcd.io/flux/flux-gh-action/#push-and-sign-kubernetes-manifests-to-container-registries">Cosign
v2.6</a> for signing Flux OCI artifacts and Helm charts, until support
for Cosign v3 is added in Flux v2.8.</p>
<h2>Components changelog</h2>
<ul>
<li>helm-controller <a
href="https://github.com/fluxcd/helm-controller/blob/v1.4.5/CHANGELOG.md">v1.4.5</a></li>
</ul>
<h2>CLI changelog</h2>
<ul>
<li>[release/v2.7.x] Update toolkit components by <a
href="https://github.com/fluxcdbot"><code>@​fluxcdbot</code></a> in <a
href="https://redirect.github.com/fluxcd/flux2/pull/5649">fluxcd/flux2#5649</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/fluxcd/flux2/compare/v2.7.4...v2.7.5">https://github.com/fluxcd/flux2/compare/v2.7.4...v2.7.5</a></p>
<h2>v2.7.4</h2>
<h2>Highlights</h2>
<p>Flux v2.7.4 is a patch release that comes with various fixes. Users
are encouraged to upgrade for the best experience.</p>
<p>ℹ️ Please follow the <a
href="https://github.com/fluxcd/flux2/discussions/5572">Upgrade
Procedure for Flux v2.7+</a> for a smooth upgrade from Flux v2.6 to the
latest version.</p>
<p>Fixes:</p>
<ul>
<li>Add <code>DisableConfigWatchers</code> feature gate to all
controllers for disabling the Secrets/ConfigMaps watchers</li>
<li>Fix Workload Identity for Azure China Cloud in all controllers</li>
<li>Update Helm Go SDK to v3.19.2 fixing schema validation issues in
helm-controller</li>
<li>Skip secret decryption for remote kustomize patches in
kustomize-controller</li>
<li>Improve post-build error reporting in kustomize-controller</li>
<li>Add <code>ArtifactGenerator</code> to aggregated RBAC roles</li>
</ul>
<p>⚠️ Note that signature verification for OCI artifacts in
source-controller is not compatible with Cosign v3.
Flux users are advised to use <a
href="https://fluxcd.io/flux/flux-gh-action/#push-and-sign-kubernetes-manifests-to-container-registries">Cosign
v2.6</a> for signing Flux OCI artifacts and Helm charts, until support
for Cosign v3 is added in Flux v2.8.</p>
<h2>Components changelog</h2>
<ul>
<li>source-controller <a
href="https://github.com/fluxcd/source-controller/blob/v1.7.4/CHANGELOG.md">v1.7.4</a></li>
<li>kustomize-controller <a
href="https://github.com/fluxcd/kustomize-controller/blob/v1.7.3/CHANGELOG.md">v1.7.3</a></li>
<li>notification-controller <a
href="https://github.com/fluxcd/notification-controller/blob/v1.7.5/CHANGELOG.md">v1.7.5</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/fluxcd/flux2/commit/8454b02a32e48d775b9f563cb51fdcb1787b5b93"><code>8454b02</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5649">#5649</a>
from fluxcd/backport-5648-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/931f101cb1cba9f7af4efa44ac0a5c7f634d9b06"><code>931f101</code></a>
Update toolkit components</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/06ed49dcd3f3ce2fc8d1988848245873a91550bc"><code>06ed49d</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5642">#5642</a>
from fluxcd/backport-5597-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/6021981de38a416f214a97dd090a1346a20d9ad4"><code>6021981</code></a>
Allow option to skip tenant namespace creation</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/4b7d46e511ca0efbea80e19fca675b18191a7508"><code>4b7d46e</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5640">#5640</a>
from fluxcd/backport-5639-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/e8c87047ba81d4bdacc3a33c443e93a35efedda0"><code>e8c8704</code></a>
Update toolkit components</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/abd603eca72aac25d6a7b2da88e902ff798fbf61"><code>abd603e</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5635">#5635</a>
from fluxcd/backport-5625-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/83d426c3c04baba957c4aa7774990563e125f5d4"><code>83d426c</code></a>
diff: report if object is skipped</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/48e77c820ecea23bb34fe51b1914bc41fd0830ac"><code>48e77c8</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5634">#5634</a>
from fluxcd/backport-5633-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/01fbe3763997a09e67ec30779aa9280cb74e8885"><code>01fbe37</code></a>
Upgrade k8s to 1.34.2, c-r to 0.22.4 and helm to 3.19.2</li>
<li>Additional commits viewable in <a
href="https://github.com/fluxcd/flux2/compare/b6e76ca2534f76dcb8dd94fb057cdfa923c3b641...8454b02a32e48d775b9f563cb51fdcb1787b5b93">compare
view</a></li>
</ul>
</details>
<br />

Updates `tj-actions/changed-files` from
70069877f29101175ed2b055d210fe8b1d54d7d7 to
abdd2f68ea150cee8f236d4a9fb4e0f2491abf1b
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tj-actions/changed-files/blob/main/HISTORY.md">tj-actions/changed-files's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h1><a
href="https://github.com/tj-actions/changed-files/compare/v46.0.5...v47.0.0">47.0.0</a>
- (2025-09-13)</h1>
<h2><!-- raw HTML omitted -->🚀 Features</h2>
<ul>
<li>Add any_added to outputs (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2567">#2567</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/c260d49a827b5eb266673bed7871c5d3ee9b5aef">c260d49</a>)
- (Jellyfrog)</li>
</ul>
<h2><!-- raw HTML omitted --> Remove</h2>
<ul>
<li>Commit and push step from build job (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2538">#2538</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/be393a90381e27c9fec2c8c2e02b00f005710145">be393a9</a>)
- (Tonye Jack)</li>
</ul>
<h2><!-- raw HTML omitted -->🔄 Update</h2>
<ul>
<li>Updated README.md (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2592">#2592</a>)</li>
</ul>
<p>Co-authored-by: github-actions[bot]
&lt;41898282+github-actions[bot]<a
href="https://github.com/users"><code>@​users</code></a>.noreply.github.com&gt;
(<a
href="https://github.com/tj-actions/changed-files/commit/3dbc1e181273d808ccff822a6e00cf18b6628ef0">3dbc1e1</a>)
- (github-actions[bot])</p>
<ul>
<li>Updated README.md (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2591">#2591</a>)</li>
</ul>
<p>Co-authored-by: github-actions[bot]
&lt;41898282+github-actions[bot]<a
href="https://github.com/users"><code>@​users</code></a>.noreply.github.com&gt;
(<a
href="https://github.com/tj-actions/changed-files/commit/b1ccff8c0892ad141d7d2de6f31e526a9dad931f">b1ccff8</a>)
- (github-actions[bot])</p>
<ul>
<li>Updated README.md (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2574">#2574</a>)</li>
</ul>
<p>Co-authored-by: github-actions[bot]
&lt;41898282+github-actions[bot]<a
href="https://github.com/users"><code>@​users</code></a>.noreply.github.com&gt;
(<a
href="https://github.com/tj-actions/changed-files/commit/050a3d3360d29711ee9d8210fc639d902d23ad07">050a3d3</a>)
- (github-actions[bot])</p>
<h2><!-- raw HTML omitted -->📚 Documentation</h2>
<ul>
<li>Update link to glob patterns (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2590">#2590</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/a892f50f7a7187bc288633c09230b09ce7ad8fd0">a892f50</a>)
- (Tonye Jack)</li>
<li>Add Jellyfrog as a contributor for code, and doc (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2573">#2573</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/f000a9b97f254f9590ff26f651cccde827ad36da">f000a9b</a>)
- (allcontributors[bot])</li>
</ul>
<h2><!-- raw HTML omitted -->🧪 Testing</h2>
<ul>
<li>Manual triggered workflows (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2637">#2637</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/c2ca2493190021783138cb8aac49bcee14b4bb89">c2ca249</a>)
- (Tonye Jack)</li>
</ul>
<h2><!-- raw HTML omitted -->⚙️ Miscellaneous Tasks</h2>
<ul>
<li><strong>deps-dev:</strong> Bump jest from 30.0.5 to 30.1.3 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2655">#2655</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/9a6755550a331fdcc8ec45443738933f8fa22eea">9a67555</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump tj-actions/git-cliff from 2.1.0 to 2.2.0
(<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2660">#2660</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/b67e30df88f43e244f4e83775e5ad8335114fb95">b67e30d</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump github/codeql-action from 3.30.2 to
3.30.3 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2661">#2661</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/62aef422ffa195474d80d73387535cf4622b2824">62aef42</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump github/codeql-action from 3.29.11 to
3.30.2 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2659">#2659</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/e874f3cddd0f54ae776e6995ae6dae4cf40fd3d3">e874f3c</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump actions/setup-node from 4.4.0 to 5.0.0
(<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2656">#2656</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/8c14441336bb3d84fd6b7fa83b6d7201c740baf5">8c14441</a>)
- (dependabot[bot])</li>
<li><strong>deps-dev:</strong> Bump <code>@​types/node</code> from
24.3.0 to 24.3.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2657">#2657</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/e995ac4be5be2bcb6e29556edc51fb63aca6b49b">e995ac4</a>)
- (dependabot[bot])</li>
<li><strong>deps-dev:</strong> Bump <code>@​types/node</code> from
24.2.1 to 24.3.0 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2649">#2649</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/3b04099b21072562f07469c10deb182b24236ca9">3b04099</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump github/codeql-action from 3.29.9 to
3.29.11 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2651">#2651</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/e7b6c977e51984988e3cc1d6b18abe2a3ba8daaa">e7b6c97</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump tj-actions/git-cliff from 2.0.2 to 2.1.0
(<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2648">#2648</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/765d62bc041415a5b494ef13d02d566128b25973">765d62b</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump github/codeql-action from 3.29.8 to
3.29.9 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2647">#2647</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/2036da178f85576f1940fedb74bb93a36cd89ab7">2036da1</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump github/codeql-action from 3.29.7 to
3.29.8 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2644">#2644</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/239aef84a5502c79a1cea96e495d17588c66c659">239aef8</a>)
- (dependabot[bot])</li>
<li><strong>deps-dev:</strong> Bump <code>@​types/node</code> from
24.2.0 to 24.2.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2645">#2645</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/a7d5f5f4919b6dbc6d3a3689887964361e8dd88f">a7d5f5f</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump actions/checkout from 4.2.2 to 5.0.0 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2646">#2646</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/5107f3abcc0c3737db51e2949f181e2c197d4d5b">5107f3a</a>)
- (dependabot[bot])</li>
<li><strong>deps-dev:</strong> Bump <code>@​types/node</code> from
24.1.0 to 24.2.0 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2640">#2640</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/f963b3f3562b00b6d2dd25efc390eb04e51ef6c6">f963b3f</a>)
- (dependabot[bot])</li>
<li><strong>deps:</strong> Bump actions/download-artifact from 4.3.0 to
5.0.0 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2641">#2641</a>)
(<a
href="https://github.com/tj-actions/changed-files/commit/f956744105e18d78bba3844a1199ce43d6503017">f956744</a>)
- (dependabot[bot])</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tj-actions/changed-files/commit/abdd2f68ea150cee8f236d4a9fb4e0f2491abf1b"><code>abdd2f6</code></a>
chore(deps): bump peter-evans/create-pull-request from 7.0.8 to 7.0.9
(<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2717">#2717</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/1d08ab228c06cfdb5c92a6be6fb2e03654e2410c"><code>1d08ab2</code></a>
chore(deps-dev): bump <code>@​types/lodash</code> from 4.17.20 to
4.17.21 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2718">#2718</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/085eb10d7ef84ec5ab690becdd4072966e781924"><code>085eb10</code></a>
chore(deps-dev): bump eslint-plugin-jest from 29.1.0 to 29.2.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2719">#2719</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/72321d1f003ac6191c4d5c7781eed4241a728447"><code>72321d1</code></a>
chore(deps): bump github/codeql-action from 4.31.4 to 4.31.5 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2720">#2720</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/8c66df4f78c44069a58c4517f775d02211a2b06b"><code>8c66df4</code></a>
chore(deps-dev): bump prettier from 3.6.2 to 3.7.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2722">#2722</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/6da3c88b60ebf09464ada9b06fba5b6f2d34bb94"><code>6da3c88</code></a>
chore(deps): bump nrwl/nx-set-shas from 4.3.3 to 4.4.0 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2712">#2712</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/48b6e9756da9107e9b08fcb676b292caaac1140b"><code>48b6e97</code></a>
chore(deps): bump actions/checkout from 5.0.0 to 5.0.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2714">#2714</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/4206138f174379c379efaa0f5c1d1f82a96eac0a"><code>4206138</code></a>
Update README.md</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/31e663cd71ad1f011b9f9e87f3a710e5ebb9a658"><code>31e663c</code></a>
chore(deps): bump github/codeql-action from 4.31.2 to 4.31.4 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2715">#2715</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/46fd332157a59040c95f13a55162240a4b789b6c"><code>46fd332</code></a>
chore(deps-dev): bump <code>@​types/node</code> from 24.10.0 to 24.10.1
(<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2711">#2711</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tj-actions/changed-files/compare/70069877f29101175ed2b055d210fe8b1d54d7d7...abdd2f68ea150cee8f236d4a9fb4e0f2491abf1b">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action` from 4.31.3 to 4.31.6
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/releases">github/codeql-action's
releases</a>.</em></p>
<blockquote>
<h2>v4.31.6</h2>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>4.31.6 - 01 Dec 2025</h2>
<p>No user facing changes.</p>
<p>See the full <a
href="https://github.com/github/codeql-action/blob/v4.31.6/CHANGELOG.md">CHANGELOG.md</a>
for more information.</p>
<h2>v4.31.5</h2>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>4.31.5 - 24 Nov 2025</h2>
<ul>
<li>Update default CodeQL bundle version to 2.23.6. <a
href="https://redirect.github.com/github/codeql-action/pull/3321">#3321</a></li>
</ul>
<p>See the full <a
href="https://github.com/github/codeql-action/blob/v4.31.5/CHANGELOG.md">CHANGELOG.md</a>
for more information.</p>
<h2>v4.31.4</h2>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>4.31.4 - 18 Nov 2025</h2>
<p>No user facing changes.</p>
<p>See the full <a
href="https://github.com/github/codeql-action/blob/v4.31.4/CHANGELOG.md">CHANGELOG.md</a>
for more information.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/github/codeql-action/blob/main/CHANGELOG.md">github/codeql-action's
changelog</a>.</em></p>
<blockquote>
<h1>CodeQL Action Changelog</h1>
<p>See the <a
href="https://github.com/github/codeql-action/releases">releases
page</a> for the relevant changes to the CodeQL CLI and language
packs.</p>
<h2>[UNRELEASED]</h2>
<p>No user facing changes.</p>
<h2>4.31.6 - 01 Dec 2025</h2>
<p>No user facing changes.</p>
<h2>4.31.5 - 24 Nov 2025</h2>
<ul>
<li>Update default CodeQL bundle version to 2.23.6. <a
href="https://redirect.github.com/github/codeql-action/pull/3321">#3321</a></li>
</ul>
<h2>4.31.4 - 18 Nov 2025</h2>
<p>No user facing changes.</p>
<h2>4.31.3 - 13 Nov 2025</h2>
<ul>
<li>CodeQL Action v3 will be deprecated in December 2026. The Action now
logs a warning for customers who are running v3 but could be running v4.
For more information, see <a
href="https://github.blog/changelog/2025-10-28-upcoming-deprecation-of-codeql-action-v3/">Upcoming
deprecation of CodeQL Action v3</a>.</li>
<li>Update default CodeQL bundle version to 2.23.5. <a
href="https://redirect.github.com/github/codeql-action/pull/3288">#3288</a></li>
</ul>
<h2>4.31.2 - 30 Oct 2025</h2>
<p>No user facing changes.</p>
<h2>4.31.1 - 30 Oct 2025</h2>
<ul>
<li>The <code>add-snippets</code> input has been removed from the
<code>analyze</code> action. This input has been deprecated since CodeQL
Action 3.26.4 in August 2024 when this removal was announced.</li>
</ul>
<h2>4.31.0 - 24 Oct 2025</h2>
<ul>
<li>Bump minimum CodeQL bundle version to 2.17.6. <a
href="https://redirect.github.com/github/codeql-action/pull/3223">#3223</a></li>
<li>When SARIF files are uploaded by the <code>analyze</code> or
<code>upload-sarif</code> actions, the CodeQL Action automatically
performs post-processing steps to prepare the data for the upload.
Previously, these post-processing steps were only performed before an
upload took place. We are now changing this so that the post-processing
steps will always be performed, even when the SARIF files are not
uploaded. This does not change anything for the
<code>upload-sarif</code> action. For <code>analyze</code>, this may
affect Advanced Setup for CodeQL users who specify a value other than
<code>always</code> for the <code>upload</code> input. <a
href="https://redirect.github.com/github/codeql-action/pull/3222">#3222</a></li>
</ul>
<h2>4.30.9 - 17 Oct 2025</h2>
<ul>
<li>Update default CodeQL bundle version to 2.23.3. <a
href="https://redirect.github.com/github/codeql-action/pull/3205">#3205</a></li>
<li>Experimental: A new <code>setup-codeql</code> action has been added
which is similar to <code>init</code>, except it only installs the
CodeQL CLI and does not initialize a database. Do not use this in
production as it is part of an internal experiment and subject to change
at any time. <a
href="https://redirect.github.com/github/codeql-action/pull/3204">#3204</a></li>
</ul>
<h2>4.30.8 - 10 Oct 2025</h2>
<p>No user facing changes.</p>
<h2>4.30.7 - 06 Oct 2025</h2>
<ul>
<li>[v4+ only] The CodeQL Action now runs on Node.js v24. <a
href="https://redirect.github.com/github/codeql-action/pull/3169">#3169</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/github/codeql-action/commit/fe4161a26a8629af62121b670040955b330f9af2"><code>fe4161a</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3336">#3336</a>
from github/update-v4.31.6-ecec1f887</li>
<li><a
href="https://github.com/github/codeql-action/commit/88c2ab5eee3b475eef2f7aabf89bd9f052153d91"><code>88c2ab5</code></a>
Update changelog for v4.31.6</li>
<li><a
href="https://github.com/github/codeql-action/commit/ecec1f88769052ebc45aa0affc53ea30d474cffa"><code>ecec1f8</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3335">#3335</a>
from github/mbg/ci/run-codeql-on-all-prs</li>
<li><a
href="https://github.com/github/codeql-action/commit/23da73277866951560f258278028b48f68958a0a"><code>23da732</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3334">#3334</a>
from github/kaspersv/overlay-minor-comments</li>
<li><a
href="https://github.com/github/codeql-action/commit/f7abc748a3da068e17cfd0e1086e8d72e51f17b6"><code>f7abc74</code></a>
Remove branch filter for PR event in CodeQL workflow</li>
<li><a
href="https://github.com/github/codeql-action/commit/32ada5e061c0433b9e40f11632c2412a55b745f9"><code>32ada5e</code></a>
Merge branch 'main' into kaspersv/overlay-minor-comments</li>
<li><a
href="https://github.com/github/codeql-action/commit/75b2f49aeaf4e8a9eab338ddc5d628eea7366eeb"><code>75b2f49</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3333">#3333</a>
from github/kaspersv/overlay-no-resource-checks-option</li>
<li><a
href="https://github.com/github/codeql-action/commit/f036b1cb781fa664100fee1f7c56a0088663dd26"><code>f036b1c</code></a>
Merge branch 'main' into kaspersv/overlay-no-resource-checks-option</li>
<li><a
href="https://github.com/github/codeql-action/commit/58c5954801c246a3975b658372285b37c45de271"><code>58c5954</code></a>
Add comment to runnerSupportsOverlayAnalysis</li>
<li><a
href="https://github.com/github/codeql-action/commit/b02fa13292ce189c02cbb1ba5488f7dbbc8c6b14"><code>b02fa13</code></a>
Order feature flags alphabetically</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/014f16e7ab1402f30e7c3329d33797e7948572db...fe4161a26a8629af62121b670040955b330f9af2">compare
view</a></li>
</ul>
</details>
<br />

<details>
<summary>Most Recent Ignore Conditions Applied to This Pull
Request</summary>

| Dependency Name | Ignore Conditions |
| --- | --- |
| crate-ci/typos | [>= 1.30.a, < 1.31] |
</details>


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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 10:32:29 +00:00
dependabot[bot] ffc3e8151a chore: bump @storybook/addon-docs from 9.1.2 to 9.1.16 in /site (#21000)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps
[@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/docs)
from 9.1.2 to 9.1.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases"><code>@​storybook/addon-docs</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v9.1.16</h2>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add `experimental_devServer` preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.15</h2>
<h2>9.1.15</h2>
<ul>
<li>Core: Add `preview-first-load` telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update `vite-plugin-storybook-nextjs` - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.14</h2>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix `play-fn` tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.12</h2>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.11</h2>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix `sb.mock` usage in Storybook's deployed in subpaths -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.10</h2>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.9</h2>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>v9.1.8</h2>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md"><code>@​storybook/addon-docs</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add <code>experimental_devServer</code> preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.15</h2>
<ul>
<li>Core: Add <code>preview-first-load</code> telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix <code>play-fn</code> tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.13</h2>
<ul>
<li>Nextjs: Fix config access for Vite - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32759">#32759</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
</ul>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix <code>sb.mock</code> usage in Storybook's deployed in
subpaths - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.7</h2>
<ul>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> to
2.0.7 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32331">#32331</a>,
thanks <a href="https://github.com/k35o"><code>@​k35o</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/storybookjs/storybook/commit/a54a04cef3ea631f2dacf3631f7f78e4453cd096"><code>a54a04c</code></a>
Bump version from &quot;9.1.15&quot; to &quot;9.1.16&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/d0d17d96288be91ae0969803cbfcd7849b9c98f8"><code>d0d17d9</code></a>
Bump version from &quot;9.1.14&quot; to &quot;9.1.15&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5afb39f85e981d380fba4658a82fac24fa5ce51b"><code>5afb39f</code></a>
Bump version from &quot;9.1.13&quot; to &quot;9.1.14&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/c2483f0e584fea0a7b4c306489b506f6165dc73b"><code>c2483f0</code></a>
Bump version from &quot;9.1.12&quot; to &quot;9.1.13&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/efe8a7ce5bf67cdef96bb4f34a787ef0d6152745"><code>efe8a7c</code></a>
Bump version from &quot;9.1.11&quot; to &quot;9.1.12&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5b2e0edf9f1b56a4708721578be83d439ebc59f5"><code>5b2e0ed</code></a>
Bump version from &quot;9.1.10&quot; to &quot;9.1.11&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/642f0cf47ed9463cecd67fdbad978113edc88196"><code>642f0cf</code></a>
Bump version from &quot;9.1.9&quot; to &quot;9.1.10&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/01867d0d587fe23765bbd43397d861a6e08223f8"><code>01867d0</code></a>
Bump version from &quot;9.1.8&quot; to &quot;9.1.9&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/28833d41b8d0e33bdc11244907fa8d14c8ddd1bf"><code>28833d4</code></a>
Bump version from &quot;9.1.7&quot; to &quot;9.1.8&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/006b304feb4cb0d2fd1408505ebeb5aababb0aad"><code>006b304</code></a>
Bump version from &quot;9.1.6&quot; to &quot;9.1.7&quot; [skip ci]</li>
<li>Additional commits viewable in <a
href="https://github.com/storybookjs/storybook/commits/v9.1.16/code/addons/docs">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​storybook/addon-docs</code> since
your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@storybook/addon-docs&package-manager=npm_and_yarn&previous-version=9.1.2&new-version=9.1.16)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 10:04:55 +00:00
dependabot[bot] 61b95314ae chore: bump @storybook/addon-themes from 9.1.2 to 9.1.16 in /site (#21005)
Bumps
[@storybook/addon-themes](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/themes)
from 9.1.2 to 9.1.16.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/releases"><code>@​storybook/addon-themes</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v9.1.16</h2>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add `experimental_devServer` preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.15</h2>
<h2>9.1.15</h2>
<ul>
<li>Core: Add `preview-first-load` telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update `vite-plugin-storybook-nextjs` - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.14</h2>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix `play-fn` tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.12</h2>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>v9.1.11</h2>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix `sb.mock` usage in Storybook's deployed in subpaths -
<a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.10</h2>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>v9.1.9</h2>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>v9.1.8</h2>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md"><code>@​storybook/addon-themes</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>9.1.16</h2>
<ul>
<li>CLI: Fix Nextjs project creation in empty directories - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32828">#32828</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Core: Add <code>experimental_devServer</code> preset - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32862">#32862</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Telemetry: Fix preview-first-load event - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32859">#32859</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.15</h2>
<ul>
<li>Core: Add <code>preview-first-load</code> telemetry - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32770">#32770</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32821">#32821</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.14</h2>
<ul>
<li>NextJS: Add NextJS 16 support - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32791">#32791</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>Addon-Vitest: Support Vitest 4 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32819">#32819</a>,
thanks <a href="https://github.com/yannbf"><code>@​yannbf</code></a> and
<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>CSF: Fix <code>play-fn</code> tag for methods - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32695">#32695</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.13</h2>
<ul>
<li>Nextjs: Fix config access for Vite - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32759">#32759</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
</ul>
<h2>9.1.12</h2>
<ul>
<li>Maintenance: Hotfix for missing nextjs dts files, thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.11</h2>
<ul>
<li>Automigration: Improve the viewport/backgrounds automigration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32619">#32619</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Mocking: Fix <code>sb.mock</code> usage in Storybook's deployed in
subpaths - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32678">#32678</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>NextJS-Vite: Automatically fix bad PostCSS configuration - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32691">#32691</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
<li>React Native Web: Fix REACT_NATIVE_AND_RNW should detect vite
builder - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32718">#32718</a>,
thanks <a
href="https://github.com/dannyhw"><code>@​dannyhw</code></a>!</li>
<li>Telemetry: Add metadata for react routers - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32615">#32615</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.10</h2>
<ul>
<li>Automigrations: Add automigration for viewport and backgrounds - <a
href="https://redirect.github.com/storybookjs/storybook/pull/31614">#31614</a>,
thanks <a
href="https://github.com/valentinpalkovic"><code>@​valentinpalkovic</code></a>!</li>
<li>Telemetry: Log userAgent in onboarding - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32566">#32566</a>,
thanks <a
href="https://github.com/shilman"><code>@​shilman</code></a>!</li>
</ul>
<h2>9.1.9</h2>
<ul>
<li>Angular: Enable experimental zoneless detection on Angular v21 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32580">#32580</a>,
thanks <a
href="https://github.com/yannbf"><code>@​yannbf</code></a>!</li>
<li>Svelte: Ignore inherited <code>HTMLAttributes</code> docgen when
using utility types - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32173">#32173</a>,
thanks <a
href="https://github.com/steciuk"><code>@​steciuk</code></a>!</li>
</ul>
<h2>9.1.8</h2>
<ul>
<li>PreactVite: Add <code>node</code> entry point - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32534">#32534</a>,
thanks <a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>!</li>
</ul>
<h2>9.1.7</h2>
<ul>
<li>Dependencies: Update <code>vite-plugin-storybook-nextjs</code> to
2.0.7 - <a
href="https://redirect.github.com/storybookjs/storybook/pull/32331">#32331</a>,
thanks <a href="https://github.com/k35o"><code>@​k35o</code></a>!</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/storybookjs/storybook/commit/a54a04cef3ea631f2dacf3631f7f78e4453cd096"><code>a54a04c</code></a>
Bump version from &quot;9.1.15&quot; to &quot;9.1.16&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/d0d17d96288be91ae0969803cbfcd7849b9c98f8"><code>d0d17d9</code></a>
Bump version from &quot;9.1.14&quot; to &quot;9.1.15&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5afb39f85e981d380fba4658a82fac24fa5ce51b"><code>5afb39f</code></a>
Bump version from &quot;9.1.13&quot; to &quot;9.1.14&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/c2483f0e584fea0a7b4c306489b506f6165dc73b"><code>c2483f0</code></a>
Bump version from &quot;9.1.12&quot; to &quot;9.1.13&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/efe8a7ce5bf67cdef96bb4f34a787ef0d6152745"><code>efe8a7c</code></a>
Bump version from &quot;9.1.11&quot; to &quot;9.1.12&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5b2e0edf9f1b56a4708721578be83d439ebc59f5"><code>5b2e0ed</code></a>
Bump version from &quot;9.1.10&quot; to &quot;9.1.11&quot; [skip
ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/642f0cf47ed9463cecd67fdbad978113edc88196"><code>642f0cf</code></a>
Bump version from &quot;9.1.9&quot; to &quot;9.1.10&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/01867d0d587fe23765bbd43397d861a6e08223f8"><code>01867d0</code></a>
Bump version from &quot;9.1.8&quot; to &quot;9.1.9&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/28833d41b8d0e33bdc11244907fa8d14c8ddd1bf"><code>28833d4</code></a>
Bump version from &quot;9.1.7&quot; to &quot;9.1.8&quot; [skip ci]</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/006b304feb4cb0d2fd1408505ebeb5aababb0aad"><code>006b304</code></a>
Bump version from &quot;9.1.6&quot; to &quot;9.1.7&quot; [skip ci]</li>
<li>Additional commits viewable in <a
href="https://github.com/storybookjs/storybook/commits/v9.1.16/code/addons/themes">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@​storybook/addon-themes</code> since
your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@storybook/addon-themes&package-manager=npm_and_yarn&previous-version=9.1.2&new-version=9.1.16)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:56:38 +00:00
dependabot[bot] 2530471922 chore: bump the react group across 1 directory with 2 updates (#20994)
Bumps the react group with 2 updates in the /site directory:
[@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react)
and
[@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom).

Updates `@types/react` from 19.2.2 to 19.2.7
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react">compare
view</a></li>
</ul>
</details>
<br />

Updates `@types/react-dom` from 19.2.2 to 19.2.3
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom">compare
view</a></li>
</ul>
</details>
<br />


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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:55:29 +00:00
dependabot[bot] fe963369ce chore: bump @types/node from 20.19.24 to 20.19.25 in /offlinedocs (#20998)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
from 20.19.24 to 20.19.25.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/node&package-manager=npm_and_yarn&previous-version=20.19.24&new-version=20.19.25)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:45:57 +00:00
dependabot[bot] fc3e0e834f chore: bump @chromatic-com/storybook from 4.1.0 to 4.1.3 in /site (#21002)
Bumps
[@chromatic-com/storybook](https://github.com/chromaui/addon-visual-tests)
from 4.1.0 to 4.1.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/chromaui/addon-visual-tests/releases"><code>@​chromatic-com/storybook</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v4.1.3</h2>
<h4>🐛 Bug Fix</h4>
<ul>
<li>Upgrade <code>chromatic</code> to v13.3.3 <a
href="https://redirect.github.com/chromaui/addon-visual-tests/pull/394">#394</a>
(<a
href="https://github.com/ghengeveld"><code>@​ghengeveld</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Gert Hengeveld (<a
href="https://github.com/ghengeveld"><code>@​ghengeveld</code></a>)</li>
</ul>
<h2>v4.1.3-next.0</h2>
<h4>🐛 Bug Fix</h4>
<ul>
<li>Upgrade <code>chromatic</code> to v13.3.3 <a
href="https://redirect.github.com/chromaui/addon-visual-tests/pull/394">#394</a>
(<a
href="https://github.com/ghengeveld"><code>@​ghengeveld</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Gert Hengeveld (<a
href="https://github.com/ghengeveld"><code>@​ghengeveld</code></a>)</li>
</ul>
<h2>v4.1.2</h2>
<h4>🐛 Bug Fix</h4>
<ul>
<li>Broaden version-range for storybook peerDependency to include
10.1.0-0 <a
href="https://redirect.github.com/chromaui/addon-visual-tests/pull/392">#392</a>
(<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<h4>Authors: 2</h4>
<ul>
<li><a
href="https://github.com/chromatic-support"><code>@​chromatic-support</code></a></li>
<li>Norbert de Langen (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<h2>v4.1.2-next.4</h2>
<h4>⚠️ Pushed to <code>next</code></h4>
<ul>
<li>Broaden version-range for storybook peerDependency to include
10.2.0-0 and 10.3.0-0 (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Norbert de Langen (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<h2>v4.1.2-next.3</h2>
<h4>⚠️ Pushed to <code>next</code></h4>
<ul>
<li>Update GitHub Actions workflow to fetch full git history and tags
with optimized settings (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Norbert de Langen (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<h2>v4.1.2-next.2</h2>
<h4>⚠️ Pushed to <code>next</code></h4>
<ul>
<li>bump yarn version (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/chromaui/addon-visual-tests/blob/v4.1.3/CHANGELOG.md"><code>@​chromatic-com/storybook</code>'s
changelog</a>.</em></p>
<blockquote>
<h1>v4.1.3 (Mon Nov 17 2025)</h1>
<h4>🐛 Bug Fix</h4>
<ul>
<li>Upgrade <code>chromatic</code> to v13.3.3 <a
href="https://redirect.github.com/chromaui/addon-visual-tests/pull/394">#394</a>
(<a
href="https://github.com/ghengeveld"><code>@​ghengeveld</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Gert Hengeveld (<a
href="https://github.com/ghengeveld"><code>@​ghengeveld</code></a>)</li>
</ul>
<hr />
<h1>v4.1.2 (Wed Oct 29 2025)</h1>
<h4>🐛 Bug Fix</h4>
<ul>
<li>Broaden version-range for storybook peerDependency to include
10.1.0-0 <a
href="https://redirect.github.com/chromaui/addon-visual-tests/pull/392">#392</a>
(<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
<li>Main <a
href="https://redirect.github.com/chromaui/addon-visual-tests/pull/391">#391</a>
(<a href="https://github.com/ndelangen"><code>@​ndelangen</code></a> <a
href="https://github.com/chromatic-support"><code>@​chromatic-support</code></a>)</li>
</ul>
<h4>Authors: 2</h4>
<ul>
<li><a
href="https://github.com/chromatic-support"><code>@​chromatic-support</code></a></li>
<li>Norbert de Langen (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<hr />
<h1>v4.1.1 (Wed Aug 20 2025)</h1>
<h4>🐛 Bug Fix</h4>
<ul>
<li>Broaden version-range for storybook peerDependency <a
href="https://redirect.github.com/chromaui/addon-visual-tests/pull/389">#389</a>
(<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<h4>Authors: 1</h4>
<ul>
<li>Norbert de Langen (<a
href="https://github.com/ndelangen"><code>@​ndelangen</code></a>)</li>
</ul>
<hr />
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/f382bd5c24d552b1bb4a6c40ed0a6e82a7723b05"><code>f382bd5</code></a>
Bump version to: 4.1.3 [skip ci]</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/eeea23948483541818a46203cf4837de084257f7"><code>eeea239</code></a>
Update CHANGELOG.md [skip ci]</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/05e1b8a5ed17a1692639cab84c376578d26f51f0"><code>05e1b8a</code></a>
Merge pull request <a
href="https://redirect.github.com/chromaui/addon-visual-tests/issues/395">#395</a>
from chromaui/next</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/bf78815c1b82c8cfd3bbfbff3fe28416dd299723"><code>bf78815</code></a>
Merge pull request <a
href="https://redirect.github.com/chromaui/addon-visual-tests/issues/394">#394</a>
from chromaui/upgrade-chromatic-cli</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/aed7067fdfc73689503b47fa1b52c13ca6a711b5"><code>aed7067</code></a>
Upgrade CLI package to v13.3.3</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/a3af186430dd5852f8109f5cbf833b88933e8dce"><code>a3af186</code></a>
Bump version to: 4.1.2 [skip ci]</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/5c28b499ed66e891e968e7147db46330d9dbebc0"><code>5c28b49</code></a>
Update CHANGELOG.md [skip ci]</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/b5fef8d290f5b6cbb45f93e3cae7282036ec3e7f"><code>b5fef8d</code></a>
Merge pull request <a
href="https://redirect.github.com/chromaui/addon-visual-tests/issues/393">#393</a>
from chromaui/next</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/dbc88e78778da6d26968b6ee72c7d47ec6e0a9a6"><code>dbc88e7</code></a>
Broaden version-range for storybook peerDependency to include 10.2.0-0
and 10...</li>
<li><a
href="https://github.com/chromaui/addon-visual-tests/commit/2b73fc62cc295aa7522975c1e386f030e20f4b67"><code>2b73fc6</code></a>
Broaden version-range for storybook peerDependency to include 10.2.0-0
and 10...</li>
<li>Additional commits viewable in <a
href="https://github.com/chromaui/addon-visual-tests/compare/v4.1.0...v4.1.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@chromatic-com/storybook&package-manager=npm_and_yarn&previous-version=4.1.0&new-version=4.1.3)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:43:30 +00:00
dependabot[bot] 77febb1469 chore: bump jsdom from 27.0.1 to 27.2.0 in /site (#21001)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 27.0.1 to 27.2.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jsdom/jsdom/releases">jsdom's
releases</a>.</em></p>
<blockquote>
<h2>Version 27.2.0</h2>
<ul>
<li>Added <code>CSSGroupingRule</code>,
<code>CSSNestedDeclarations</code>, <code>CSSConditionRule</code>,
<code>CSSContainerRule</code>, <code>CSSScopeRule</code>,
<code>CSSSupportsRule</code>, <code>CSSLayerBlockRule</code>, and
<code>CSSLayerStatementRule</code> to jsdom <code>Window</code>s.
(acemir)</li>
<li>Improved CSS parsing and CSSOM object APIs via updates to <a
href="https://www.npmjs.com/package/@acemir/cssom"><code>@acemir/cssom</code></a>.
(acemir)</li>
<li>Fixed <code>@import</code>-ed stylesheets to be properly exposed to
CSSOM, and not to overwrite the sheet created from the
<code>&lt;link&gt;</code> or <code>&lt;style&gt;</code> element.
(acemir)</li>
</ul>
<h2>Version 27.1.0</h2>
<ul>
<li>Improved CSS parsing by switching to <a
href="https://www.npmjs.com/package/@acemir/cssom"><code>@acemir/cssom</code></a>,
including support for nested selectors, nested declarations, layer
statements, and improved at-rule validation. (acemir)</li>
<li>Fixed some selector cache invalidation issues where changes to
attributes were not being picked up. (asamuzaK)</li>
<li>Fixed <code>package.json</code> <code>&quot;engines&quot;</code>
field to reflect the new minimum Node.js versions needed to run jsdom,
as noted in the changelog for v27.0.1.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/jsdom/jsdom/blob/main/Changelog.md">jsdom's
changelog</a>.</em></p>
<blockquote>
<h2>27.2.0</h2>
<ul>
<li>Added <code>CSSGroupingRule</code>,
<code>CSSNestedDeclarations</code>, <code>CSSConditionRule</code>,
<code>CSSContainerRule</code>, <code>CSSScopeRule</code>,
<code>CSSSupportsRule</code>, <code>CSSLayerBlockRule</code>, and
<code>CSSLayerStatementRule</code> to jsdom <code>Window</code>s.
(acemir)</li>
<li>Improved CSS parsing and CSSOM object APIs via updates to <a
href="https://www.npmjs.com/package/@acemir/cssom"><code>@acemir/cssom</code></a>.
(acemir)</li>
<li>Fixed <code>@import</code>-ed stylesheets to be properly exposed to
CSSOM, and not to overwrite the sheet created from the
<code>&lt;link&gt;</code> or <code>&lt;style&gt;</code> element.
(acemir)</li>
</ul>
<h2>27.1.0</h2>
<ul>
<li>Improved CSS parsing by switching to <a
href="https://www.npmjs.com/package/@acemir/cssom"><code>@acemir/cssom</code></a>,
including support for nested selectors, nested declarations, layer
statements, and improved at-rule validation. (acemir)</li>
<li>Fixed some selector cache invalidation issues where changes to
attributes were not being picked up. (asamuzaK)</li>
<li>Fixed <code>package.json</code> <code>&quot;engines&quot;</code>
field to reflect the new minimum Node.js versions needed to run jsdom,
as noted in the changelog for v27.0.1.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jsdom/jsdom/commit/b0805a908fb905ec69c4d1afc09977226927ae09"><code>b0805a9</code></a>
Version 27.2.0</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/3e07e1e1a93e5f67d6aac93046c99da94bc47625"><code>3e07e1e</code></a>
Update dependencies and dev dependencies</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/931aabedb686bb612b34afca4dc803f86976f426"><code>931aabe</code></a>
Various CSSOM improvements</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/70741dab9a9733c8c359ae82745269c5de607e44"><code>70741da</code></a>
Add failing tests for border shorthand property parsing</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/b282400b448d34477dcf539f0e5c9654e2ed4a0c"><code>b282400</code></a>
Update <code>@​acemir/cssom</code> dependency</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/adb999a12912f2f5ceb49fde6b1c9f7051968dc8"><code>adb999a</code></a>
Version 27.1.0</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/91f40c4bb1ef7c814b01b8e24db33356dc233eb1"><code>91f40c4</code></a>
Update dependencies and dev dependencies</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/ebad33c3ce5eb9c2fdfb81aaa5c0ab200626aac1"><code>ebad33c</code></a>
Note more strict minimum version requirement</li>
<li><a
href="https://github.com/jsdom/jsdom/commit/bd02585e2fd07bf846490779fba4696462d2eb94"><code>bd02585</code></a>
Swap rweb-cssom to <code>@​acemir/cssom</code></li>
<li><a
href="https://github.com/jsdom/jsdom/commit/f15c8302a03d0e9ccdef743e8297ff2e18e3f748"><code>f15c830</code></a>
Add failing test for cssText setter</li>
<li>Additional commits viewable in <a
href="https://github.com/jsdom/jsdom/compare/27.0.1...27.2.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=jsdom&package-manager=npm_and_yarn&previous-version=27.0.1&new-version=27.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:32:50 +00:00
dependabot[bot] 154baf3d45 chore: bump github.com/anthropics/anthropic-sdk-go from 1.18.0 to 1.19.0 (#21013)
Bumps
[github.com/anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go)
from 1.18.0 to 1.19.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-go/releases">github.com/anthropics/anthropic-sdk-go's
releases</a>.</em></p>
<blockquote>
<h2>v1.19.0</h2>
<h2>1.19.0 (2025-11-24)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.18.1...v1.19.0">v1.18.1...v1.19.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> adds support for Claude Opus 4.5, Effort,
Advance Tool Use Features, Autocompaction, and Computer Use v5 (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/a03391cb00b8c78c79fd8bfe447f00d78f37db25">a03391c</a>)</li>
</ul>
<h2>v1.18.1</h2>
<h2>1.18.1 (2025-11-19)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.18.0...v1.18.1">v1.18.0...v1.18.1</a></p>
<h3>Bug Fixes</h3>
<ul>
<li><strong>structured outputs:</strong> use correct beta header (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/09ec0a647b1a108bb7c74e4c7b1016502ca781bb">09ec0a6</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/anthropics/anthropic-sdk-go/blob/main/CHANGELOG.md">github.com/anthropics/anthropic-sdk-go's
changelog</a>.</em></p>
<blockquote>
<h2>1.19.0 (2025-11-24)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.18.1...v1.19.0">v1.18.1...v1.19.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> adds support for Claude Opus 4.5, Effort,
Advance Tool Use Features, Autocompaction, and Computer Use v5 (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/a03391cb00b8c78c79fd8bfe447f00d78f37db25">a03391c</a>)</li>
</ul>
<h2>1.18.1 (2025-11-19)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.18.0...v1.18.1">v1.18.0...v1.18.1</a></p>
<h3>Bug Fixes</h3>
<ul>
<li><strong>structured outputs:</strong> use correct beta header (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/09ec0a647b1a108bb7c74e4c7b1016502ca781bb">09ec0a6</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/0e4a219d952e839fbbfe42e54282e44c1c28f1fb"><code>0e4a219</code></a>
release: 1.19.0</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/9ea2999a49dac535ab07ff6a94aaf70f4ec3b85a"><code>9ea2999</code></a>
feat(api): adds support for Claude Opus 4.5, Effort, Advance Tool Use
Feature...</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/9d1fca29394cf4a2aff51e99b4b089882cf0b769"><code>9d1fca2</code></a>
release: 1.18.1</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/f79df507220e2a46ca26e00562fd0300de1fe99f"><code>f79df50</code></a>
fix(structured outputs): use correct beta header</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/9c3ce43f8b134b0f74449bf258f5a6828f80f59d"><code>9c3ce43</code></a>
codegen metadata</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.18.0...v1.19.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/anthropics/anthropic-sdk-go&package-manager=go_modules&previous-version=1.18.0&new-version=1.19.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:30:28 +00:00
dependabot[bot] ba370f1daa chore: bump react-router from 7.9.5 to 7.9.6 in /site (#21006)
Bumps
[react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router)
from 7.9.5 to 7.9.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/releases">react-router's
releases</a>.</em></p>
<blockquote>
<h2>v7.9.6</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v796">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v796</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md">react-router's
changelog</a>.</em></p>
<blockquote>
<h2>7.9.6</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>[UNSTABLE] Add <code>location</code>/<code>params</code> as arguments
to client-side <code>unstable_onError</code> to permit enhanced error
reporting. (<a
href="https://redirect.github.com/remix-run/react-router/pull/14509">#14509</a>)</p>
<p>⚠️ This is a breaking change if you've already adopted
<code>unstable_onError</code>. The second <code>errorInfo</code>
parameter is now an object with <code>location</code> and
<code>params</code>:</p>
<pre lang="tsx"><code>// Before
function errorHandler(error: unknown, errorInfo?: React.errorInfo) {
  /*...*/
}
<p>// After
function errorHandler(
error: unknown,
info: {
location: Location;
params: Params;
errorInfo?: React.ErrorInfo;
},
) {
/<em>...</em>/
}
</code></pre></p>
</li>
<li>
<p>Properly handle ancestor thrown middleware errors before
<code>next()</code> on fetcher submissions (<a
href="https://redirect.github.com/remix-run/react-router/pull/14517">#14517</a>)</p>
</li>
<li>
<p>Fix issue with splat routes interfering with multiple calls to
patchRoutesOnNavigation (<a
href="https://redirect.github.com/remix-run/react-router/pull/14487">#14487</a>)</p>
</li>
<li>
<p>Normalize double-slashes in <code>resolvePath</code> (<a
href="https://redirect.github.com/remix-run/react-router/pull/14529">#14529</a>)</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/remix-run/react-router/commit/e75da95e16ecf625f4e3bbc864b1a0a5202052c2"><code>e75da95</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14538">#14538</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/6104e1fc91b5b9485573b7b0c17ab17ecda6ca33"><code>6104e1f</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14535">#14535</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/02e65a55daa6f9c0aa88d0de8732330e0b449dad"><code>02e65a5</code></a>
Normalize double-slashes in resolvePath (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14529">#14529</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/092c872603c2cba6498144ef988437773ff89438"><code>092c872</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14523">#14523</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/cd6eb8d4e034d9ee9038050c53d8b2d46a073988"><code>cd6eb8d</code></a>
Fix bug with fetcher submission ancestor-thrown middleware errors (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14517">#14517</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/fc01722e301b909a736fe312ec5bac4c1f5c1c26"><code>fc01722</code></a>
Add location/params arguments to client-side unstable_onError (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14509">#14509</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/7c115a6850a0b7652ff40086daec6544a9cb40a1"><code>7c115a6</code></a>
Fix splat routes blocking multiple FOW calls (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14487">#14487</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/89e2bfe8232ad7c24cf610b0998e9028dcfa9ce8"><code>89e2bfe</code></a>
chore: format</li>
<li>See full diff in <a
href="https://github.com/remix-run/react-router/commits/react-router@7.9.6/packages/react-router">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for react-router since your current
version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=react-router&package-manager=npm_and_yarn&previous-version=7.9.5&new-version=7.9.6)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:24:54 +00:00
dependabot[bot] 4431e9aef7 chore: bump the coder-modules group across 3 directories with 11 updates (#21011)
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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:23:53 +00:00
dependabot[bot] ccf8fd6c58 chore: bump jest-fixed-jsdom from 0.0.10 to 0.0.11 in /site (#21012)
Bumps [jest-fixed-jsdom](https://github.com/mswjs/jest-fixed-jsdom) from
0.0.10 to 0.0.11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/mswjs/jest-fixed-jsdom/releases">jest-fixed-jsdom's
releases</a>.</em></p>
<blockquote>
<h2>v0.0.11 (2025-11-14)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>add WritableStream (<a
href="https://redirect.github.com/mswjs/jest-fixed-jsdom/issues/40">#40</a>)
(b73393cb3a8171cf9cf43e6e790d64bbbe03c242) <a
href="https://github.com/jamiemoyes"><code>@​jamiemoyes</code></a> <a
href="https://github.com/jamie-moyes-depop"><code>@​jamie-moyes-depop</code></a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/mswjs/jest-fixed-jsdom/commit/f4ef52d727c1860b883785cef9f73509008c7def"><code>f4ef52d</code></a>
chore(release): v0.0.11</li>
<li><a
href="https://github.com/mswjs/jest-fixed-jsdom/commit/b73393cb3a8171cf9cf43e6e790d64bbbe03c242"><code>b73393c</code></a>
fix: add WritableStream (<a
href="https://redirect.github.com/mswjs/jest-fixed-jsdom/issues/40">#40</a>)</li>
<li>See full diff in <a
href="https://github.com/mswjs/jest-fixed-jsdom/compare/v0.0.10...v0.0.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=jest-fixed-jsdom&package-manager=npm_and_yarn&previous-version=0.0.10&new-version=0.0.11)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:23:00 +00:00
dependabot[bot] e713870b69 chore: bump @types/lodash from 4.17.20 to 4.17.21 in /site (#21010)
Bumps
[@types/lodash](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lodash)
from 4.17.20 to 4.17.21.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lodash">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/lodash&package-manager=npm_and_yarn&previous-version=4.17.20&new-version=4.17.21)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:20:57 +00:00
dependabot[bot] 8bb481566b chore: bump @tailwindcss/typography from 0.5.16 to 0.5.19 in /site (#21009)
Bumps
[@tailwindcss/typography](https://github.com/tailwindlabs/tailwindcss-typography)
from 0.5.16 to 0.5.19.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/tailwindlabs/tailwindcss-typography/releases"><code>@​tailwindcss/typography</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v0.5.19</h2>
<h3>Fixed</h3>
<ul>
<li>Fixed broken color styles (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/405">#405</a>)</li>
</ul>
<h2>v0.5.18</h2>
<h3>Fixed</h3>
<ul>
<li>Fixed undefined variable error (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/403">#403</a>)</li>
</ul>
<h2>v0.5.17</h2>
<h3>Added</h3>
<ul>
<li>Add modifiers for description list elements (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/357">#357</a>)</li>
<li>Add <code>prose-picture</code> modifier (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/367">#367</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Include unit in <code>hr</code> border-width value (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/379">#379</a>)</li>
<li>Ensure <code>&lt;kbd&gt;</code> styles work with Tailwind CSS v4 (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/387">#387</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Remove lodash dependencies (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/402">#402</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/tailwindlabs/tailwindcss-typography/blob/main/CHANGELOG.md"><code>@​tailwindcss/typography</code>'s
changelog</a>.</em></p>
<blockquote>
<h2>[0.5.19] - 2025-09-24</h2>
<h3>Fixed</h3>
<ul>
<li>Fixed broken color styles (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/405">#405</a>)</li>
</ul>
<h2>[0.5.18] - 2025-09-19</h2>
<h3>Fixed</h3>
<ul>
<li>Fixed undefined variable error (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/403">#403</a>)</li>
</ul>
<h2>[0.5.17] - 2025-09-19</h2>
<h3>Added</h3>
<ul>
<li>Add modifiers for description list elements (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/357">#357</a>)</li>
<li>Add <code>prose-picture</code> modifier (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/367">#367</a>)</li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Include unit in <code>hr</code> border-width value (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/379">#379</a>)</li>
<li>Ensure <code>&lt;kbd&gt;</code> styles work with Tailwind CSS v4 (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/387">#387</a>)</li>
</ul>
<h3>Changed</h3>
<ul>
<li>Remove lodash dependencies (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/pull/402">#402</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/e002ab89ad8f4202638249c1c300c0cf0b3739c5"><code>e002ab8</code></a>
0.5.19</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/bbb1c21099e34ff4d1d7f82f7528b85e71ed3c5a"><code>bbb1c21</code></a>
Fix bad RGB syntax (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/405">#405</a>)</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/b316f958af5bc12a981526c3091d8319626e274e"><code>b316f95</code></a>
0.5.18</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/ed952066e698dbb65a2f082eeb903ccba5a6834a"><code>ed95206</code></a>
Fix variable declaration in opacity function (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/403">#403</a>)</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/7efcb4a499e6ede67088e28393a906d4d089e580"><code>7efcb4a</code></a>
0.5.17</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/e0ec248bafa002d589509e29bfd9f054570e6d85"><code>e0ec248</code></a>
chore(ci): update actions for release insiders</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/511afcb0bd9732eb8fcdc703f35ff76e57bfcd7b"><code>511afcb</code></a>
Add modifiers for description list elements (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/357">#357</a>)</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/042a531528cd3ddecafda94fe972394dc8aab6ae"><code>042a531</code></a>
Add <code>prose-picture</code> modifiers (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/367">#367</a>)</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/f822222ae6e289e8cc0b23636891dc3545d5682a"><code>f822222</code></a>
Fix <code>kbd</code> shadow colors not being calculated on oklch colors
(<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/387">#387</a>)</li>
<li><a
href="https://github.com/tailwindlabs/tailwindcss-typography/commit/ecb7e87a52d86afbbff64200d40f05fe59433039"><code>ecb7e87</code></a>
Add Tailwind v4 custom color theme example to README (<a
href="https://redirect.github.com/tailwindlabs/tailwindcss-typography/issues/396">#396</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/tailwindlabs/tailwindcss-typography/compare/v0.5.16...v0.5.19">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@tailwindcss/typography&package-manager=npm_and_yarn&previous-version=0.5.16&new-version=0.5.19)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:20:30 +00:00
dependabot[bot] 5a78ec1428 chore: bump humanize-duration from 3.32.2 to 3.33.1 in /site (#21008)
Bumps
[humanize-duration](https://github.com/EvanHahn/HumanizeDuration.js)
from 3.32.2 to 3.33.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/EvanHahn/HumanizeDuration.js/blob/main/HISTORY.md">humanize-duration's
changelog</a>.</em></p>
<blockquote>
<h1>3.33.1 / 2025-09-15</h1>
<ul>
<li>change: shrink size slightly</li>
</ul>
<h1>3.33.0 / 2025-06-05</h1>
<ul>
<li>new: Serbian Latin support (<code>sr_Latn</code>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/7d96bbc85bc7c04397518afbb4183f8dc81f1b62"><code>7d96bbc</code></a>
3.33.1</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/8e7cf83314beceb5d4387980c060ce6b84ee7ce1"><code>8e7cf83</code></a>
Update changelog and bower.json for 3.33.1 release</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/eb2ab9d406f832080ea7236125602a75d41b2fbe"><code>eb2ab9d</code></a>
Shorten definition of &quot;ones&quot; languages, like English</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/aa943ce284ca96afdf1439be696c72ec5de5d425"><code>aa943ce</code></a>
Shorten definitions of Slavic languages</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/2e310914ded5fee0f3cc32af75455b0bd0e16154"><code>2e31091</code></a>
Minor: shrink condition in <code>language</code> helper by a few
bytes</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/3fa60af062bfbf8cbb273a27e5f13b9d49e6b041"><code>3fa60af</code></a>
Remove unnecessary <code>@ts-check</code> directives</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/1e520bbe2808a64307a9cfb2de4d12950a5a9a99"><code>1e520bb</code></a>
Update devDependencies to latest versions</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/46098849ce4afb49098a1d4631e272432edebe6e"><code>4609884</code></a>
Add funding metadata to package</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/1f03ec67a772a36a95056b864554989bba5023a8"><code>1f03ec6</code></a>
3.33.0</li>
<li><a
href="https://github.com/EvanHahn/HumanizeDuration.js/commit/7c18165182968a8120a19237562a40fffe7863c7"><code>7c18165</code></a>
Update changelog and bower.json for 3.33.0 release</li>
<li>Additional commits viewable in <a
href="https://github.com/EvanHahn/HumanizeDuration.js/compare/v3.32.2...v3.33.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=humanize-duration&package-manager=npm_and_yarn&previous-version=3.32.2&new-version=3.33.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:20:06 +00:00
dependabot[bot] cfd6c4bc13 chore: bump the vite group across 1 directory with 3 updates (#20995)
Bumps the vite group with 3 updates in the /site directory:
[@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react),
[vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) and
[vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).

Updates `@vitejs/plugin-react` from 5.1.0 to 5.1.1
<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>plugin-react@5.1.1</h2>
<h3>Update code to support newer <code>rolldown-vite</code> (<a
href="https://redirect.github.com/vitejs/vite-plugin-react/pull/976">#976</a>)</h3>
<p><code>rolldown-vite</code> will remove
<code>optimizeDeps.rollupOptions</code> in favor of
<code>optimizeDeps.rolldownOptions</code> soon. This plugin now uses
<code>optimizeDeps.rolldownOptions</code> to support newer
<code>rolldown-vite</code>. Please update <code>rolldown-vite</code> to
the latest version if you are using an older version.</p>
</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>5.1.1 (2025-11-12)</h2>
<h3>Update code to support newer <code>rolldown-vite</code> (<a
href="https://redirect.github.com/vitejs/vite-plugin-react/pull/976">#976</a>)</h3>
<p><code>rolldown-vite</code> will remove
<code>optimizeDeps.rollupOptions</code> in favor of
<code>optimizeDeps.rolldownOptions</code> soon. This plugin now uses
<code>optimizeDeps.rolldownOptions</code> to support newer
<code>rolldown-vite</code>. Please update <code>rolldown-vite</code> to
the latest version if you are using an older version.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/23db72731b7c9c3d57a8188f0395d2ec90a6e2f6"><code>23db727</code></a>
release: plugin-react@5.1.1</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/bcc7db076ec038ab0152fd00a712913569c901a4"><code>bcc7db0</code></a>
chore: add changelog for <a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/976">#976</a>
and <a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/978">#978</a></li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/4a2e229b2093b4a2e4af1c07f3e07aa91f3e12a5"><code>4a2e229</code></a>
fix(react): use rolldownOptions instead of deprecated rollupOptions in
optimi...</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/41cb8237bfb902fe1873c55de0780f0ca2cf3640"><code>41cb823</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/968">#968</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/9cabe2720f571338cc319c957f285e6f787f23fa"><code>9cabe27</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/960">#960</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/c8d918eab8d8cb0f9d38966d5f29a113a0c397ac"><code>c8d918e</code></a>
chore(react): use ts-ignore for ecosystem-ci (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/956">#956</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/0849e420b30a6183c9364aae2320435684696090"><code>0849e42</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/953">#953</a>)</li>
<li>See full diff in <a
href="https://github.com/vitejs/vite-plugin-react/commits/plugin-react@5.1.1/packages/plugin-react">compare
view</a></li>
</ul>
</details>
<br />

Updates `vite` from 7.1.12 to 7.2.6
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/releases">vite's
releases</a>.</em></p>
<blockquote>
<h2>v7.2.6</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.6/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v7.2.5</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.5/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<p><em>Note: 7.2.5 failed to publish so it is skipped on npm</em></p>
<h2>v7.2.4</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.4/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v7.2.3</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.3/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v7.2.2</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.2/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>plugin-legacy@7.2.1</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/plugin-legacy@7.2.1/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v7.2.1</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>plugin-legacy@7.2.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/plugin-legacy@7.2.0/packages/plugin-legacy/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v7.2.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v7.2.0-beta.1</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.0-beta.1/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
<h2>v7.2.0-beta.0</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.2.0-beta.0/packages/vite/CHANGELOG.md">CHANGELOG.md</a>
for details.</p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md">vite's
changelog</a>.</em></p>
<blockquote>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v7.2.5...v7.2.6">7.2.6</a>
(2025-12-01)<!-- raw HTML omitted --></h2>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v7.2.4...v7.2.5">7.2.5</a>
(2025-12-01)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>config:</strong> handle shebang properly (<a
href="https://redirect.github.com/vitejs/vite/issues/21158">#21158</a>)
(<a
href="https://github.com/vitejs/vite/commit/df5a30d2690a2ebc4824a79becdcef30538dc602">df5a30d</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21146">#21146</a>)
(<a
href="https://github.com/vitejs/vite/commit/a3cd262f37228967e455617e982b35fccc49ffe9">a3cd262</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21175">#21175</a>)
(<a
href="https://github.com/vitejs/vite/commit/72e398a46d8d2f54fbcbeb9ff0dceab346aeb642">72e398a</a>)</li>
<li>fix <code>external: true</code> merging (<a
href="https://redirect.github.com/vitejs/vite/issues/21164">#21164</a>)
(<a
href="https://github.com/vitejs/vite/commit/5ef557a96c4a1f2b3a3aa25c12df3ee87b4a03f5">5ef557a</a>)</li>
<li>shortcuts not rebound after server restart (<a
href="https://redirect.github.com/vitejs/vite/issues/21166">#21166</a>)
(<a
href="https://github.com/vitejs/vite/commit/3765f7baea36234bf3816eeed38776d27bfd3649">3765f7b</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>deps:</strong> replace debug with obug (<a
href="https://redirect.github.com/vitejs/vite/issues/21137">#21137</a>)
(<a
href="https://github.com/vitejs/vite/commit/203a5512a42a1031f685993f5d9cbae5f328354f">203a551</a>)</li>
</ul>
<h3>Documentation</h3>
<ul>
<li>clarify manifest.json <code>imports</code> field is JS chunks only
(<a
href="https://redirect.github.com/vitejs/vite/issues/21136">#21136</a>)
(<a
href="https://github.com/vitejs/vite/commit/46d3077f2b63771cc50230bc907c48f5773c00fb">46d3077</a>)</li>
</ul>
<h3>Miscellaneous Chores</h3>
<ul>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21174">#21174</a>)
(<a
href="https://github.com/vitejs/vite/commit/74559c947483a8ee24da052ac2d9568f7cb3546a">74559c9</a>)</li>
</ul>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v7.2.3...v7.2.4">7.2.4</a>
(2025-11-20)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li>revert &quot;perf(deps): replace debug with obug (<a
href="https://redirect.github.com/vitejs/vite/issues/21107">#21107</a>)&quot;
(<a
href="https://github.com/vitejs/vite/commit/2d66b7b14aa6dfd62f3d6a59ee8382ed5ca6fd32">2d66b7b</a>)</li>
</ul>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v7.2.2...v7.2.3">7.2.3</a>
(2025-11-20)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li>allow multiple <code>bindCLIShortcuts</code> calls with shortcut
merging (<a
href="https://redirect.github.com/vitejs/vite/issues/21103">#21103</a>)
(<a
href="https://github.com/vitejs/vite/commit/5909efd8fbfd1bf1eab65427aea0613124b2797a">5909efd</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21096">#21096</a>)
(<a
href="https://github.com/vitejs/vite/commit/6a34ac3422686e7cf7cc9a25d299cb8e5a8d92a0">6a34ac3</a>)</li>
<li><strong>deps:</strong> update all non-major dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21128">#21128</a>)
(<a
href="https://github.com/vitejs/vite/commit/4f8171eb3046bd70c83964689897dab4c6b58bc0">4f8171e</a>)</li>
</ul>
<h3>Performance Improvements</h3>
<ul>
<li><strong>deps:</strong> replace debug with obug (<a
href="https://redirect.github.com/vitejs/vite/issues/21107">#21107</a>)
(<a
href="https://github.com/vitejs/vite/commit/acfe939e1f7c303c34b0b39b883cc302da767fa2">acfe939</a>)</li>
</ul>
<h3>Miscellaneous Chores</h3>
<ul>
<li><strong>deps:</strong> update dependency
<code>@​rollup/plugin-commonjs</code> to v29 (<a
href="https://redirect.github.com/vitejs/vite/issues/21099">#21099</a>)
(<a
href="https://github.com/vitejs/vite/commit/02ceaec45e17bef19159188a28d9196fed1761be">02ceaec</a>)</li>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21095">#21095</a>)
(<a
href="https://github.com/vitejs/vite/commit/39a0a15fd24ed37257c48b795097a3794e54d255">39a0a15</a>)</li>
<li><strong>deps:</strong> update rolldown-related dependencies (<a
href="https://redirect.github.com/vitejs/vite/issues/21127">#21127</a>)
(<a
href="https://github.com/vitejs/vite/commit/50297208452241061cb44d09a4bbdf77a11ac01e">5029720</a>)</li>
</ul>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v7.2.1...v7.2.2">7.2.2</a>
(2025-11-07)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li>revert &quot;refactor: use fs.cpSync (<a
href="https://redirect.github.com/vitejs/vite/issues/21019">#21019</a>)&quot;
(<a
href="https://redirect.github.com/vitejs/vite/issues/21081">#21081</a>)
(<a
href="https://github.com/vitejs/vite/commit/728c8eeebc0ad7ba48e680f46bbdb55020b2e152">728c8ee</a>)</li>
</ul>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v7.2.0...v7.2.1">7.2.1</a>
(2025-11-06)<!-- raw HTML omitted --></h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitejs/vite/commit/bda5dbb648fa7cf877ea9c76ba8a7da226b65cce"><code>bda5dbb</code></a>
release: v7.2.6</li>
<li><a
href="https://github.com/vitejs/vite/commit/3aa7527fb4fc7dafe3ab57c41d637d2985c7bb6e"><code>3aa7527</code></a>
release: v7.2.5</li>
<li><a
href="https://github.com/vitejs/vite/commit/72e398a46d8d2f54fbcbeb9ff0dceab346aeb642"><code>72e398a</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21175">#21175</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/3765f7baea36234bf3816eeed38776d27bfd3649"><code>3765f7b</code></a>
fix: shortcuts not rebound after server restart (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21166">#21166</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/5ef557a96c4a1f2b3a3aa25c12df3ee87b4a03f5"><code>5ef557a</code></a>
fix: fix <code>external: true</code> merging (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21164">#21164</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/74559c947483a8ee24da052ac2d9568f7cb3546a"><code>74559c9</code></a>
chore(deps): update rolldown-related dependencies (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21174">#21174</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/df5a30d2690a2ebc4824a79becdcef30538dc602"><code>df5a30d</code></a>
fix(config): handle shebang properly (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21158">#21158</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/a3cd262f37228967e455617e982b35fccc49ffe9"><code>a3cd262</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21146">#21146</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/46d3077f2b63771cc50230bc907c48f5773c00fb"><code>46d3077</code></a>
docs: clarify manifest.json <code>imports</code> field is JS chunks only
(<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21136">#21136</a>)</li>
<li><a
href="https://github.com/vitejs/vite/commit/203a5512a42a1031f685993f5d9cbae5f328354f"><code>203a551</code></a>
perf(deps): replace debug with obug (<a
href="https://github.com/vitejs/vite/tree/HEAD/packages/vite/issues/21137">#21137</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/vitejs/vite/commits/v7.2.6/packages/vite">compare
view</a></li>
</ul>
</details>
<br />

Updates `vitest` from 4.0.6 to 4.0.14
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases">vitest's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.14</h2>
<h3>   🚀 Experimental Features</h3>
<ul>
<li><strong>browser</strong>: Expose
<code>utils.configurePrettyDOM</code>  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9103">vitest-dev/vitest#9103</a>
<a href="https://github.com/vitest-dev/vitest/commit/2cc34e0d4"><!-- raw
HTML omitted -->(2cc34)<!-- raw HTML omitted --></a></li>
<li><strong>runner</strong>: Add full names to tasks  -  by <a
href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9087">vitest-dev/vitest#9087</a>
<a href="https://github.com/vitest-dev/vitest/commit/821aa2002"><!-- raw
HTML omitted -->(821aa)<!-- raw HTML omitted --></a></li>
<li><strong>ui</strong>: Add tabbed failure view for
<code>toMatchScreenshot</code> with comparison slider  -  by <a
href="https://github.com/macarie"><code>@​macarie</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/8813">vitest-dev/vitest#8813</a>
<a href="https://github.com/vitest-dev/vitest/commit/c37c2eb0b"><!-- raw
HTML omitted -->(c37c2)<!-- raw HTML omitted --></a></li>
</ul>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Externalize before caching  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9077">vitest-dev/vitest#9077</a>
<a href="https://github.com/vitest-dev/vitest/commit/e1b2e086a"><!-- raw
HTML omitted -->(e1b2e)<!-- raw HTML omitted --></a></li>
<li>Collect the duration of external imports  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9097">vitest-dev/vitest#9097</a>
<a href="https://github.com/vitest-dev/vitest/commit/3326cc9f4"><!-- raw
HTML omitted -->(3326c)<!-- raw HTML omitted --></a></li>
<li>Rename <code>collect</code> to <code>import</code>, remove
<code>prepare</code>  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9091">vitest-dev/vitest#9091</a>
<a href="https://github.com/vitest-dev/vitest/commit/1256b5ca3"><!-- raw
HTML omitted -->(1256b)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>:
<ul>
<li>Unsubscribe <code>onCancel</code> on rpc destroy  -  by <a
href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9088">vitest-dev/vitest#9088</a>
<a href="https://github.com/vitest-dev/vitest/commit/f5b72374b"><!-- raw
HTML omitted -->(f5b72)<!-- raw HTML omitted --></a></li>
<li>Revert the viewport scaling in non-ui mode <a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9018">#9018</a>
 -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9072">vitest-dev/vitest#9072</a>
and <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9018">vitest-dev/vitest#9018</a>
<a href="https://github.com/vitest-dev/vitest/commit/64502a2c4"><!-- raw
HTML omitted -->(64502)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>coverage</strong>:
<ul>
<li>Invalidate circular modules correctly on rerun with coverage  -  by
<a href="https://github.com/aicest"><code>@​aicest</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9096">vitest-dev/vitest#9096</a>
<a href="https://github.com/vitest-dev/vitest/commit/6f22c675f"><!-- raw
HTML omitted -->(6f22c)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>expect</strong>:
<ul>
<li>Allow function as standard schema  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9099">vitest-dev/vitest#9099</a>
<a href="https://github.com/vitest-dev/vitest/commit/ed8a2ebbd"><!-- raw
HTML omitted -->(ed8a2)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>jsdom</strong>:
<ul>
<li>Reuse abort signals if possible  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9090">vitest-dev/vitest#9090</a>
<a href="https://github.com/vitest-dev/vitest/commit/2c468ee95"><!-- raw
HTML omitted -->(2c468)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>pool</strong>:
<ul>
<li>Init <code>VITEST_POOL_ID</code> + <code>VITEST_WORKER_ID</code>
before environment setup  -  by <a
href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9085">vitest-dev/vitest#9085</a>
<a href="https://github.com/vitest-dev/vitest/commit/379185b40"><!-- raw
HTML omitted -->(37918)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>web-worker</strong>:
<ul>
<li><code>postMessage</code> to send ports to workers  -  by <a
href="https://github.com/whitphx"><code>@​whitphx</code></a> and <a
href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9078">vitest-dev/vitest#9078</a>
<a href="https://github.com/vitest-dev/vitest/commit/9d1763d11"><!-- raw
HTML omitted -->(9d176)<!-- raw HTML omitted --></a></li>
</ul>
</li>
</ul>
<h3>   🏎 Performance</h3>
<ul>
<li>Replace <code>debug</code> with <code>obug</code>  -  by <a
href="https://github.com/sxzz"><code>@​sxzz</code></a> and <a
href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/9057">vitest-dev/vitest#9057</a>
<a href="https://github.com/vitest-dev/vitest/commit/acc5152b9"><!-- raw
HTML omitted -->(acc51)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.0.13...v4.0.14">View
changes on GitHub</a></h5>
<h2>v4.0.13</h2>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li><strong>types</strong>:
<ul>
<li>Don't use type from Vite 7.1  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9071">vitest-dev/vitest#9071</a>
<a href="https://github.com/vitest-dev/vitest/commit/6356b1d38"><!-- raw
HTML omitted -->(6356b)<!-- raw HTML omitted --></a></li>
<li>Don't import node.js dependent types in vitest/browser  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9068">vitest-dev/vitest#9068</a>
<a href="https://github.com/vitest-dev/vitest/commit/332afa0de"><!-- raw
HTML omitted -->(332af)<!-- raw HTML omitted --></a></li>
</ul>
</li>
</ul>
<h3>   🏎 Performance</h3>
<ul>
<li>Avoid fetchModule roundtrip if the module is cached  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9075">vitest-dev/vitest#9075</a>
<a href="https://github.com/vitest-dev/vitest/commit/b27e002e5"><!-- raw
HTML omitted -->(b27e0)<!-- raw HTML omitted --></a></li>
<li><strong>experimental</strong>: If <code>fsCacheModule</code> is
enabled, read from the memory when possible  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9076">vitest-dev/vitest#9076</a>
<a href="https://github.com/vitest-dev/vitest/commit/6b9a1b5b1"><!-- raw
HTML omitted -->(6b9a1)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.0.12...v4.0.13">View
changes on GitHub</a></h5>
<h2>v4.0.12</h2>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Inherit <code>fsModuleCachePath</code> by default  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/9063">vitest-dev/vitest#9063</a>
<a href="https://github.com/vitest-dev/vitest/commit/9a8bc78c5"><!-- raw
HTML omitted -->(9a8bc)<!-- raw HTML omitted --></a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitest-dev/vitest/commit/9ca74cfb2060d8bc1c7a319ba3cba1578517adb0"><code>9ca74cf</code></a>
chore: release v4.0.14</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/821aa20021111de63a71e8a9c69eb9188d6e409a"><code>821aa20</code></a>
feat(runner): Add full names to tasks (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9087">#9087</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/1256b5ca34a36d3a29479d5dfddb129348964d80"><code>1256b5c</code></a>
fix: rename <code>collect</code> to <code>import</code>, remove
<code>prepare</code> (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9091">#9091</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/3326cc9f43f102322f3c627590d103d8a3890dd5"><code>3326cc9</code></a>
fix: collect the duration of external imports (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9097">#9097</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/379185b408baba90ec91540b5e7cf545a4527f1a"><code>379185b</code></a>
fix(pool): init <code>VITEST_POOL_ID</code> +
<code>VITEST_WORKER_ID</code> before environment setu...</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/2c468ee95ee1d42129f59665eabc563e34dae1e4"><code>2c468ee</code></a>
fix(jsdom): reuse abort signals if possible (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9090">#9090</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/e1b2e086a40ce154ae11714fa71749ec21b1ac23"><code>e1b2e08</code></a>
fix: externalize before caching (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9077">#9077</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/acc5152b9690992e3ac0cff691db4347f2dccdf9"><code>acc5152</code></a>
perf: replace <code>debug</code> with <code>obug</code> (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9057">#9057</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/73b54ce2859d34f3847de465efb3f6affda0f8c1"><code>73b54ce</code></a>
chore: release v4.0.13</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/b27e002e578e7b6cf182c3c173ac5d8fd390598d"><code>b27e002</code></a>
perf: avoid fetchModule roundtrip if the module is cached (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/9075">#9075</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/vitest-dev/vitest/commits/v4.0.14/packages/vitest">compare
view</a></li>
</ul>
</details>
<br />


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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:15:13 +00:00
dependabot[bot] 5f8575dbaf chore: bump the radix group across 1 directory with 4 updates (#20993)
Bumps the radix group with 4 updates in the /site directory:
[@radix-ui/react-avatar](https://github.com/radix-ui/primitives),
[@radix-ui/react-label](https://github.com/radix-ui/primitives),
[@radix-ui/react-separator](https://github.com/radix-ui/primitives) and
[@radix-ui/react-slot](https://github.com/radix-ui/primitives).

Updates `@radix-ui/react-avatar` from 1.1.10 to 1.1.11
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/radix-ui/primitives/commits">compare
view</a></li>
</ul>
</details>
<br />

Updates `@radix-ui/react-label` from 2.1.7 to 2.1.8
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/radix-ui/primitives/commits">compare
view</a></li>
</ul>
</details>
<br />

Updates `@radix-ui/react-separator` from 1.1.7 to 1.1.8
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/radix-ui/primitives/commits">compare
view</a></li>
</ul>
</details>
<br />

Updates `@radix-ui/react-slot` from 1.2.3 to 1.2.4
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/radix-ui/primitives/commits">compare
view</a></li>
</ul>
</details>
<br />


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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:12:53 +00:00
dependabot[bot] 0415d1f84a chore: bump @types/lodash from 4.17.20 to 4.17.21 in /offlinedocs (#20997)
Bumps
[@types/lodash](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lodash)
from 4.17.20 to 4.17.21.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lodash">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/lodash&package-manager=npm_and_yarn&previous-version=4.17.20&new-version=4.17.21)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:12:22 +00:00
dependabot[bot] 0e10b315f2 chore: bump prettier from 3.6.2 to 3.7.3 in /offlinedocs (#20996)
Bumps [prettier](https://github.com/prettier/prettier) from 3.6.2 to
3.7.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/releases">prettier's
releases</a>.</em></p>
<blockquote>
<h2>3.7.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix <code>prettier.getFileInfo()</code> change that breaks VSCode
extension by <a
href="https://github.com/fisker"><code>@​fisker</code></a> in <a
href="https://redirect.github.com/prettier/prettier/pull/18375">prettier/prettier#18375</a></li>
</ul>
<p>🔗 <a
href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md#373">Changelog</a></p>
<h2>3.7.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix string print when switching quotes by <a
href="https://github.com/fisker"><code>@​fisker</code></a> in <a
href="https://redirect.github.com/prettier/prettier/pull/18351">prettier/prettier#18351</a></li>
<li>Preserve quote for embedded HTML attribute values by <a
href="https://github.com/kovsu"><code>@​kovsu</code></a> in <a
href="https://redirect.github.com/prettier/prettier/pull/18352">prettier/prettier#18352</a></li>
<li>Fix comment in empty type literal by <a
href="https://github.com/fisker"><code>@​fisker</code></a> in <a
href="https://redirect.github.com/prettier/prettier/pull/18364">prettier/prettier#18364</a></li>
</ul>
<p>🔗 <a
href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md#372">Changelog</a></p>
<h2>3.7.1</h2>
<ul>
<li>Fix performance regression in doc printer (<a
href="https://redirect.github.com/prettier/prettier/pull/18342">#18342</a>
by <a href="https://github.com/fisker"><code>@​fisker</code></a>)</li>
</ul>
<p>🔗 <a
href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md#371">Changelog</a></p>
<h2>3.7.0</h2>
<p><a
href="https://github.com/prettier/prettier/compare/3.6.2...3.7.0">diff</a></p>
<p>🔗 <a href="https://prettier.io/blog/2025/11/27/3.7.0">Release
note</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/prettier/prettier/blob/main/CHANGELOG.md">prettier's
changelog</a>.</em></p>
<blockquote>
<h1>3.7.3</h1>
<p><a
href="https://github.com/prettier/prettier/compare/3.7.2...3.7.3">diff</a></p>
<h4>API: Fix <code>prettier.getFileInfo()</code> change that breaks
VSCode extension (<a
href="https://redirect.github.com/prettier/prettier/pull/18375">#18375</a>
by <a href="https://github.com/fisker"><code>@​fisker</code></a>)</h4>
<p>An internal refactor accidentally broke the VSCode extension plugin
loading.</p>
<h1>3.7.2</h1>
<p><a
href="https://github.com/prettier/prettier/compare/3.7.1...3.7.2">diff</a></p>
<h4>JavaScript: Fix string print when switching quotes (<a
href="https://redirect.github.com/prettier/prettier/pull/18351">#18351</a>
by <a href="https://github.com/fisker"><code>@​fisker</code></a>)</h4>
<!-- raw HTML omitted -->
<pre lang="jsx"><code>// Input
console.log(&quot;A descriptor\\'s .kind must be \&quot;method\&quot; or
\&quot;field\&quot;.&quot;)
<p>// Prettier 3.7.1
console.log('A descriptor\'s .kind must be &quot;method&quot; or
&quot;field&quot;.');</p>
<p>// Prettier 3.7.2
console.log('A descriptor\'s .kind must be &quot;method&quot; or
&quot;field&quot;.');
</code></pre></p>
<h4>JavaScript: Preserve quote for embedded HTML attribute values (<a
href="https://redirect.github.com/prettier/prettier/pull/18352">#18352</a>
by <a href="https://github.com/kovsu"><code>@​kovsu</code></a>)</h4>
<!-- raw HTML omitted -->
<pre lang="tsx"><code>// Input
const html = /* HTML */ ` &lt;div
class=&quot;${styles.banner}&quot;&gt;&lt;/div&gt; `;
<p>// Prettier 3.7.1
const html = /* HTML */ <code>&amp;lt;div
class=${styles.banner}&amp;gt;&amp;lt;/div&amp;gt;</code>;</p>
<p>// Prettier 3.7.2
const html = /* HTML */ <code>&amp;lt;div
class=&amp;quot;${styles.banner}&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;</code>;
</code></pre></p>
<h4>TypeScript: Fix comment in empty type literal (<a
href="https://redirect.github.com/prettier/prettier/pull/18364">#18364</a>
by <a href="https://github.com/fisker"><code>@​fisker</code></a>)</h4>
<!-- raw HTML omitted -->
<pre lang="tsx"><code>// Input
export type XXX = {
  // tbd
};
<p>// Prettier 3.7.1
&lt;/tr&gt;&lt;/table&gt;
</code></pre></p>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/prettier/prettier/commit/fdfa6701767f5140a85902ecc9fb6444f5b4e3f8"><code>fdfa670</code></a>
Release 3.7.3</li>
<li><a
href="https://github.com/prettier/prettier/commit/2dce3ec09081427775cc93a8d92cb828a0129e6f"><code>2dce3ec</code></a>
Fix typo</li>
<li><a
href="https://github.com/prettier/prettier/commit/27d6c645cadeebe86011a195e8058d29888a68f6"><code>27d6c64</code></a>
Revert previous change to <code>getFileInfo</code> (<a
href="https://redirect.github.com/prettier/prettier/issues/18375">#18375</a>)</li>
<li><a
href="https://github.com/prettier/prettier/commit/f4a7afaebfa27b975f6b4e336091cd600b0f5592"><code>f4a7afa</code></a>
Add types for config related functions (<a
href="https://redirect.github.com/prettier/prettier/issues/18376">#18376</a>)</li>
<li><a
href="https://github.com/prettier/prettier/commit/9266e3e85b0dd4c594554cf9a91988e20c006f9b"><code>9266e3e</code></a>
Add resolved test cases (<a
href="https://redirect.github.com/prettier/prettier/issues/18358">#18358</a>)</li>
<li><a
href="https://github.com/prettier/prettier/commit/3bfc014442370ebad42b42e8eceea6d25891148d"><code>3bfc014</code></a>
Bump Prettier dependency to 3.7.2</li>
<li><a
href="https://github.com/prettier/prettier/commit/081b84695b060651dc221afcda7531f4c7731c2e"><code>081b846</code></a>
Clean changelog_unreleased</li>
<li><a
href="https://github.com/prettier/prettier/commit/03384c964d99ef26cb1a7fec68e7e5e263220cea"><code>03384c9</code></a>
Release 3.7.2</li>
<li><a
href="https://github.com/prettier/prettier/commit/514e51afa2046aac7beb651270f0f4ce74a3dafa"><code>514e51a</code></a>
Release <code>@​prettier/plugin-hermes</code> &amp;
<code>@​prettier/plugin-oxc</code> v0.1.2</li>
<li><a
href="https://github.com/prettier/prettier/commit/29a11ae1ae417b8d0fa66d88d656001a6a90e297"><code>29a11ae</code></a>
Fix comment in empty type literal (<a
href="https://redirect.github.com/prettier/prettier/issues/18364">#18364</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/prettier/prettier/compare/3.6.2...3.7.3">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for prettier since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=prettier&package-manager=npm_and_yarn&previous-version=3.6.2&new-version=3.7.3)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 09:12:12 +00:00
Atif Ali 012d1cbd39 chore: fix dependabot terraform module grouping pattern (#20992) 2025-12-01 13:51:56 +05:00
Ethan 782a1052c8 test: use toHaveValue() to avoid flaky parameter verification (#20990)
## Problem

The test `create workspace with default and required parameters` was
flaky because `verifyParameters` in `site/e2e/helpers.ts` didn't wait
for input values to be populated before asserting.

After PR #20710 removed classic parameters, the form now uses dynamic
parameters loaded asynchronously via WebSocket. The input field can be
visible before its value is populated.

Closes https://github.com/coder/internal/issues/1154

## Fix

Replace immediate read + assertion:
```typescript
const value = await parameterField.inputValue();
expect(value).toEqual(buildParameter.value);
```

With Playwright's auto-retrying assertion:
```typescript
await expect(parameterField).toHaveValue(buildParameter.value);
```

From [Playwright docs for
`inputValue()`](https://playwright.dev/docs/api/class-locator#locator-input-value):

> **NOTE** If you need to assert input value, prefer
`expect(locator).toHaveValue(value[, options])` to avoid flakiness. See
assertions guide for more details.

---

This PR was fully generated by [mux](https://github.com/coder/mux), and
reviewed by a human.
2025-12-01 13:46:19 +11:00
dependabot[bot] 7d45d078f2 chore: bump coder/code-server/coder from 1.4.0 to 1.4.1 in /dogfood/coder-envbuilder (#20988)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)



[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/code-server/coder&package-manager=terraform&previous-version=1.4.0&new-version=1.4.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 00:49:17 +00:00
dependabot[bot] 9179a5971b chore: bump coder/code-server/coder from 1.4.0 to 1.4.1 in /dogfood/coder (#20984)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/code-server/coder&package-manager=terraform&previous-version=1.4.0&new-version=1.4.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 00:49:07 +00:00
dependabot[bot] 976cc61686 chore: bump coder/mux/coder from 1.0.1 to 1.0.2 in /dogfood/coder (#20987)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/mux/coder&package-manager=terraform&previous-version=1.0.1&new-version=1.0.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 00:49:01 +00:00
dependabot[bot] bc7278d306 chore: bump coder/git-config/coder from 1.0.31 to 1.0.32 in /dogfood/coder (#20985)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/git-config/coder&package-manager=terraform&previous-version=1.0.31&new-version=1.0.32)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 00:48:53 +00:00
dependabot[bot] ea8694cb65 chore: bump coder/zed/coder from 1.1.1 to 1.1.2 in /dogfood/coder (#20986)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/zed/coder&package-manager=terraform&previous-version=1.1.1&new-version=1.1.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 00:48:49 +00:00
dependabot[bot] 8e32f86e44 chore: bump coder/vscode-web/coder from 1.4.1 to 1.4.2 in /dogfood/coder (#20983)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/vscode-web/coder&package-manager=terraform&previous-version=1.4.1&new-version=1.4.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-01 00:48:35 +00:00
Susana Ferreira f8d9a8046f feat: add notification warning alert to Tasks page (#20900)
## Problem

Users may not realize that task notifications are disabled by default.
To improve awareness, we show a warning alert on the Tasks page when all
task notifications are disabled.

**Alert visibility logic:**
- Shows when **all** task notification templates (Task Working, Task
Idle, Task Completed, Task Failed) are disabled
- Can be dismissed by the user, which stores the dismissal in the user
preferences API
- If the user later enables any task notification in Account Settings,
the dismissal state is cleared so the alert will show again if they
disable all notifications in the future

<img width="2980" height="1588" alt="Screenshot 2025-11-25 at 17 48 17"
src="https://github.com/user-attachments/assets/316bf097-d9d2-4489-bc16-2987ba45f45c"
/>

## Changes

- Added a warning alert to the Tasks page when all task notifications
are disabled
- Introduced new `/users/{user}/preferences` endpoint to manage user
preferences (stored in `user_configs` table)
- Alert is dismissible and stores the dismissal state via the new user
preferences API endpoint
- Enabling any task notification in Account Settings clears the
dismissal state via the preferences API
- Added comprehensive Storybook stories for both TasksPage and
NotificationsPage to test all alert visibility states and interactions

Closes: https://github.com/coder/internal/issues/1089
2025-11-28 16:50:59 +00:00
Marcin Tojek a8862be546 feat(site): add tab to invalidate prebuilds (#20864)
Updates https://github.com/coder/coder/issues/17917
2025-11-28 08:44:38 +01:00
Sas Swart ce627bf23f feat: implement agent socket api, client and cli (#20758)
closes: https://github.com/coder/coder/issues/10352
closes: https://github.com/coder/internal/issues/1094
closes: https://github.com/coder/internal/issues/1095

In this pull request, we enable a new set of experimental cli commands
grouped under `coder exp sync`.
These commands allow any process acting within a coder workspace to
inform the coder agent of its requirements and execution progress. The
coder agent will then relay this information to other processes that
have subscribed.

These commands are:
```
# Check if this feature is enabled in your environment 
coder exp sync ping

# express that your unit depends on another
coder exp sync want <unit> <dependency_unit> 

# express that your unit intends to start a portion of the script that requires 
# other units to have completed first. This command blocks until all dependencies have been met
coder exp sync start <unit> 

# express that your unit has completes its work, allowing dependent units to begin their execution
coder exp sync complete <unit>
```

Example:

In order to automatically run claude code in a new workspace, it must
first have a git repository cloned. The scripts responsible for cloning
the repository and for running claude code would coordinate in the
following way:

```bash
# Script A: Claude code

# Inform the agent that the claude script wants the git script.
# That is, the git script must have completed before the claude script can begin its execution
coder exp sync want claude git

# Inform the agent that we would now like to begin execution of claude.
# This command will block until the git script (and any other defined dependencies)
# have completed
coder exp sync start claude

# Now we run claude code and any other commands we need
claude ...

# Once our script has completed, we inform the agent, so that any scripts that depend on this one
# may begin their execution

coder exp sync complete claude
```

```bash
# Script B: Git

# Because the git script does not have any dependencies, we can simply inform the agent that we 
# intend to start
coder exp sync start git

git clone ssh://git@github.com/coder/coder

# Once the repository have been cloned, we inform the agent that this script is complete, so that
# scripts that depend on it may begin their execution.
coder exp sync complete git
```

Notes:
* Unit names (ie. `claude` and `git`) given as input to the sync
commands are arbitrary strings. You do not have to conform to specific
identifiers. We recommend naming your scripts descriptively, but
succinctly.
* Scripts unit names should be well documented. Other scripts will need
to know the names you've chosen in order to depend on yours. Therefore,
you

---------

Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
2025-11-28 08:33:50 +02:00
Mathias Fredriksson ee58f40cad feat(site): add bulk delete for tasks (#20905)
This change implements bulk delete for tasks, closely copying UI and
components from workspaces batch actions.

Fixes coder/internal#1088
2025-11-27 16:05:17 +00:00
Susana Ferreira 21efebeadc fix: show task display name in task topbar (#20957)
## Description

Update task topbar in task page to show display name, instead of task
name.

Follow-up PR: https://github.com/coder/coder/pull/20918
Related to internal slack thread:
https://codercom.slack.com/archives/C0992H8HGCS/p1764086497375829
2025-11-27 15:57:35 +00:00
Michael Suchacz dba34da981 fix: make mux mandatory (#20969)
<!--

If you have used AI to produce some or all of this PR, please ensure you
have read our [AI Contribution
guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
before submitting.

-->
2025-11-27 15:02:17 +00:00
Sas Swart 1d726c81bb fix: remove a sensitive field from an agent log line (#20968)
This PR removes a log field that could expose sensitive information in
agent logs for workspaces that pass such information to the agent via
its manifest.
2025-11-27 16:12:03 +02:00
Danny Kopping ebbdfa03b8 chore: document bedrock setup process for aibridge (#20956)
Documents the steps needed to setup AWS Bedrock

See also: https://github.com/coder/coder/pull/20507

---------

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-27 10:14:16 +02:00
Jake Howell caf711d70a fix: ensure we check if the user can actually see ai bridge (#20942)
There was a mild regression here where-in if the user only had `AI
Bridge` they wouldn't be able to see this content in the dropdown menu.
This was necessary for reasons earlier with it being an experiment
however its now fine to check for this and won't upset anything.
2025-11-27 17:45:51 +11:00
Callum Styan d22d34e45b fix: pass context with authorization to agentapi (#20959)
The agentapi context needs to be a context with some amount of
authorization attached to it via the context so that the cache refresh
routine can fetch the workspace from the db via GetWorkspaceForAgentID.

---------

Signed-off-by: Callum Styan <callumstyan@gmail.com>
2025-11-26 14:53:16 -08:00
Yevhenii Shcherbina a6a8a060ea docs: update boundary docs (#20958) 2025-11-26 15:33:55 -05:00
Atif Ali e3671f38ff docs: change AI Bridge state from 'early access' to 'beta' (#20951)
<!--

If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting.

-->
2025-11-27 01:05:30 +05:00
Mathias Fredriksson bcc74b2664 docs: improve code comment guidelines for AI agents (#20952)
This PR enhances the CLAUDE.md document with comprehensive guidelines
for writing better code comments, specifically targeted at AI agents and
LLM-generated code.

## Changes

- **Proper sentence structure**: Comments should end with punctuation
- **Explain why, not what**: Focus on rationale rather than describing
code
- **Line length and wrapping**: 80-character width with natural wrapping

## Example

The guidelines include before/after examples showing the difference
between well-formatted, meaningful comments and poorly written ones.

## Impact

These standards will help ensure AI-generated code includes
professional, maintainable comments that align with project conventions.

---

🤖 This change was written by Claude Sonnet 4.5 Thinking using
[mux](https://github.com/coder/mux) and reviewed by a human 🏂
2025-11-26 18:46:37 +02:00
Mathias Fredriksson 363ed5f64a docs: consolidate cursorrules into AGENTS.md (#20950)
Replace `.cursorrules` with symlink to `AGENTS.md` to establish a single
authoritative document for AI agent guidelines.

Extract architectural documentation from `.cursorrules` into
`.claude/docs/ARCHITECTURE.md` for reference material.

This ensures all AI agents (Claude, Cursor, etc.) use the same
guidelines without duplication.

---

🤖 This change was written by Claude Sonnet 4.5 Thinking using
[mux](https://github.com/coder/mux) and reviewed by a human 🏂
2025-11-26 16:13:16 +02:00
Marcin Tojek 9c7135a61d chore: add license check for prebuilds (#20947)
Related: https://github.com/coder/coder/pull/20864
2025-11-26 15:00:07 +01:00
Mathias Fredriksson b7d8918d60 fix(site): only show active tasks in waiting for input tab (#20933)
This change filters out non-active tasks from the "Waiting for input"
tab filter for the tasks list.

---

🤖 This change was initially written by Claude Code using Coder Tasks, then reviewed and edited by a human 🏂
2025-11-26 13:13:39 +00:00
Danielle Maywood e7dbbcde87 fix: do not notify marked for deletion for deleted workspaces (#20937)
Closes https://github.com/coder/coder/issues/20913

I've ran the test without the fix, verified the test caught the issue,
then applied the fix, and confirmed the issue no longer happens.

---

🤖 PR was initially written by Claude Opus 4.5 Thinking using Claude Code
and then review by a human 👩
2025-11-26 09:23:16 +00:00
Zach bbf7b137da fix(cli): remove defaulting to keyring when --global-config set (#20943)
This fixes a regression that caused the VS code extension to be unable
to authenticate after making keyring usage on by default. This is
because the VS code extension assumes the CLI will always use the
session token stored on disk, specifically in the directory specified by
--global-config.

This fix makes keyring usage enabled when the --global-config directory
is not set. This is a bit wonky but necessary to allow the extension to
continue working without modification and without backwards compat
concerns. In the future we should modify these extensions to either
access the credential in the keyring (like Coder Desktop) or some other
approach that doesn't rely on the session token being stored on disk.

Tests:
`coder login dev.coder.com` -> token stored in keyring
`coder login --global-config=/tmp/ dev.coder.com` -> token stored in
`/tmp/session`
2025-11-26 10:17:31 +01:00
Mykyta Protsenko c87c33f7dd perf: add index to improve the GetWorkspaceAgentByInstanceID query performance (#20936)
## Context

GetWorkspaceAgentByInstanceID has a suboptimal plan. Even though it is
designed to fetch a small subset of records, there are no corresponding
indexes and that query results in full table scan:

Query:

```
SELECT id, auth_instance_id FROM workspace_agents
where auth_instance_id='i-013c2b96b6441648a' and deleted=FALSE;
```

Plan:

```
------------------------------------------------------------------------------------------------------------------
 Seq Scan on workspace_agents  (cost=0.00..222325.48 rows=2 width=36) (actual time=0.012..234.152 rows=4 loops=1)
   Filter: ((NOT deleted) AND ((auth_instance_id)::text = 'i-013c2b96b6441648a'::text))
   Rows Removed by Filter: 302276
 Planning Time: 0.173 ms
 Execution Time: 234.169 ms
```

After adding the index, the plan improves drastically.

Updated plan:

```
 Bitmap Heap Scan on workspace_agents  (cost=4.44..12.32 rows=2 width=36) (actual time=0.019..0.019 rows=0 loops=1)
   Recheck Cond: (((auth_instance_id)::text = 'i-013c2b96b6441648a'::text) AND (NOT deleted))
   ->  Bitmap Index Scan on workspace_agents_auth_instance_id_deleted_idx  (cost=0.00..4.44 rows=2 width=0) (actual time=0.013..0.014 rows=0 loops=1)
         Index Cond: (((auth_instance_id)::text = 'i-013c2b96b6441648a'::text) AND (deleted = false))
 Planning Time: 0.388 ms
 Execution Time: 0.044 ms
```

## Changes

* add an index to optimize this query

## Testing

* ran the queries manually against prod and test DBs
* ran `./scripts/develop.sh`, connected to the local PostgreSQL
instance, inspected the indexes to make sure new index is there:

```
Indexes:
    "workspace_agents_pkey" PRIMARY KEY, btree (id)
    // NEW INDEX CREATED SUCCESSFULLY  [comment is mine]
    "workspace_agents_auth_instance_id_deleted_idx" btree (auth_instance_id, deleted)
    "workspace_agents_auth_token_idx" btree (auth_token)
    "workspace_agents_resource_id_idx" btree (resource_id)
```

---------

Signed-off-by: Danny Kopping <danny@coder.com>
Co-authored-by: Danny Kopping <danny@coder.com>
2025-11-26 05:57:25 +02:00
George K a9261577bc perf: optimize migration 371 to run faster on large deployments (#20906)
closes https://github.com/coder/coder/issues/20899

This is in response to a migration in v2.27 that takes very long on
deployments with large `api_keys` tables.

NOTE: The optimization causes the _up_ migration to delete old data
(keys that expired more than 7 days ago). The _down_ migration won't
resurrect the deleted data.
2025-11-25 21:44:59 -06:00
Benjamin Cohen 9c2f94b574 fix(site): remove erroneous "install Cursor" notification for Cursor Desktop (#20875)
### Summary

This change removes the erroneous “Install Cursor” notification in the
desktop environment when Cursor is already installed. The issue is the
timeout of 500ms was simply too short for Cursor Desktop to respond in
time, so I increased it to 1500ms. This seems to consistently work, but
it could easily be increased to 2000ms to be safe.

### Issue

Fixes #20289

### Testing

- Verified that when Cursor is installed, the notification no longer
appears

### QA

#### Before


https://github.com/user-attachments/assets/facd2e74-6eb7-47ac-935d-7b11974648a0

#### After


https://github.com/user-attachments/assets/ced817d8-ca0c-428c-8436-5f30ffc6134b
2025-11-26 12:59:06 +11:00
Zach 6238a99275 feat(cli)!: enable keyring usage by default (#20851)
Make keyring usage for session token storage on by default for supported
platforms (Windows and macOS), with the ability to opt-out via
--use-keyring=false.

This change will be a breaking change for any users depending on the
session token being stored on disk, though users can restore file usage
via the flag above.

This change will also require CLI users to authenticate after updating.
2025-11-25 18:13:00 -07:00
Asher c266bb830c chore: add debug logging and recovery to agent api requests (#20785)
This is to debug context timeouts on API requests to the agent.

Because rbac and database cannot be imported in slim, split the logger
middleware into slim and non-slim versions and break out the recovery
middleware.
2025-11-25 14:59:20 -09:00
Callum Styan b0e8384b82 perf: reduce DB calls to GetWorkspaceByAgentID via caching workspace info (#20662)
---------

Signed-off-by: Callum Styan <callumstyan@gmail.com>
2025-11-25 14:45:05 -08:00
ケイラ 956cbe7751 chore: remove classic parameters frontend code (#20710) 2025-11-25 15:07:21 -07:00
Andrew Aquino 4863812d8c refactor: replace MUI Tooltip component with Tooltip (simple usage) (#20849)
for #19974 

Redo of #20027, this time splitting it into multiple PRs + using our
existing `Tooltip` component instead of creating a new component (see
below). This PR covers the most basic usage of the MUI Tooltip, i.e.,
the tooltip content is a string literal.

~~Adds a global `TooltipProvider` to `AppProviders` and our Storybook
decorators, so that we don't have to render a `TooltipProvider` for
every tooltip instance. Removing redundant `TooltipProvider`s will be
another separate PR~~ <- this was done by #20869
2025-11-25 13:40:26 -08:00
Danny Kopping e340560164 chore: actually store translated token metadata (#20929)
Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-25 16:50:19 +00:00
Mathias Fredriksson e189dc1f81 fix: complete Tasks GA promotion (docs, site) (#20927)
## Summary

Completes the Coder Tasks GA promotion by updating swagger tags and
regenerating API documentation and updating the frontend API structure.

## Related

Follows #20923 and #20921 which promoted Tasks from Beta/Experimental to
GA.

---

🤖 This change was written by Claude Sonnet 4.5 Thinking using
[mux](https://github.com/coder/mux) and reviewed by a human 🏂
2025-11-25 16:46:13 +00:00
Susana Ferreira 2f399eafae feat(site): use display name field for tasks (#20918)
## Description

This PR updates the frontend to use the new `display_name` field for
tasks. In the tasks list view, `display_name` replaces `initial_prompt`,
and in the tasks sidebar, `display_name` replaces `name`. This is a
follow-up to https://github.com/coder/coder/pull/20856, which introduced
the `display_name` field in the backend.

## Changes

- Display `task.display_name` instead of `task.initial_prompt` in the
tasks table
- Display `task.display_name` instead of `task.name` in the task sidebar
view
- Updated mock data to include `display_name` for all test tasks
- Added Storybook story to showcase display name rendering with
different lengths (short, max length with ellipsis, and edge cases)

Follow-up: https://github.com/coder/coder/pull/20856
Closes: https://github.com/coder/coder/issues/20801
2025-11-25 16:29:54 +00:00
Mathias Fredriksson 02bac71421 feat: promote Tasks to GA (#20923)
## Summary

This change promotes Coder Tasks from Beta to GA by removing Beta labels
from:

- TasksPage UI component
- Documentation files

Tasks feature is now ready for general availability!

---

🤖 This change was written by Claude Sonnet 4.5 Thinking using
[mux](https://github.com/coder/mux) and reviewed by a human 🏂
2025-11-25 17:43:31 +02:00
Danielle Maywood b255827a52 chore: promote tasks to stable from experimental (#20921)
- Promote tasks from `/api/experimental` to `/api/v2`.
- Move sdk from `ExperimentalClient` to `Client`.
- Update swagger
2025-11-25 15:24:25 +00:00
Mathias Fredriksson 37fc6646ad perf(coderd/database): limit GetLatestWorkspaceAppStatusByAppID to 1 row (#20917)
## Description

This PR fixes an issue where `GetLatestWorkspaceAppStatusesByAppID`
returned an unbounded number of rows for a given app ID, which could
cause performance issues for noisy or long-running AI tasks.

## Impact

This change reduces database query overhead for workspace app status
updates, particularly for busy AI tasks that update their status
frequently. Previously, fetching the latest status would return all
historical statuses, now it returns only the most recent one.

Fixes #20862

---

🤖 This change was written by Claude Sonnet 4.5 Thinking using [mux](https://github.com/coder/mux) and reviewed by a human 🏄🏻‍♂️
2025-11-25 16:56:42 +02:00
Yevhenii Shcherbina 5213023fe5 chore: update boundary to v0.2.1 (#20920)
Update boundary to v0.2.1 which uses sys-admin permissions to work with
newer kernel versions.
2025-11-25 09:17:20 -05:00
Danny Kopping ae2c94b322 chore: add @jdomeracki-coder as CODEOWNER of .github dir (#20919)
Supply-chain attacks are on the rise; Jakub is going to keep an eye on
things.

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-25 13:58:22 +00:00
Mathias Fredriksson ad8ba4aac6 feat(cli): promote tasks commands from experimental to GA (#20916)
## Overview

This change promotes the tasks CLI commands from `coder exp task` to
`coder task`, marking them as generally available (GA).

## Migration

Users will need to update their scripts from:

```shell
coder exp task create "my task"
```

To:
```shell
coder task create "my task"
```

---

🤖 This change was written by Claude Sonnet 4.5 Thinking using [mux](https://github.com/coder/mux) and reviewed by a human 🏄🏻‍♂️
2025-11-25 13:50:22 +00:00
Susana Ferreira 3011207519 feat: add display name field for tasks (#20856)
## Problem

Tasks currently only expose a machine-friendly name field (e.g.
`task-python-debug-a1b2`), but this value is primarily an identifier
rather than a clean, descriptive label. We need a separate
display-friendly name for use in the UI.

This PR introduces a new `display_name` field and updates the task-name
generation flow. The Claude system prompt was updated to return valid
JSON with both `name` and `display_name`. The name generation logic
follows a fallback chain (Anthropic > prompt sanitization > random
fallback). To make task names more closely resemble their display names,
the legacy `task-` prefix has been removed. For context, PR
https://github.com/coder/coder/pull/20834 introduced a small Task icon
to the workspace list to help identify workspaces associated to tasks.

## Changes

- Database migration: Added `display_name` column to tasks table
- Updated system prompt to generate both task name and display name as
valid JSON
- Task name generation now follows a fallback chain: Anthropic > prompt
sanitization > random fallback
- Removed `task-` prefix from task names to allow more descriptive names
- Note: PR https://github.com/coder/coder/pull/20834 adds a Task icon to
workspaces in the workspace list to distinguish task-created workspaces

**Note:** UI changes will be addressed in a follow-up PR

Related to: https://github.com/coder/coder/issues/20801
2025-11-25 13:00:59 +00:00
Atif Ali e8bf074022 chore: update AI client compatibility table in AI Bridge documentation (#20915) 2025-11-25 12:29:47 +00:00
Danielle Maywood 7fd9a450c1 docs: update dev containers documentation to reflect GA status (#20847)
Updates the dev containers documentation to accurately reflect that the
feature is generally available and document all configuration options.

Closes https://github.com/coder/internal/issues/1138

---

🤖 PR was written by Claude Sonnet 4.5 Thinking using [Coder
Mux](https://github.com/coder/cmux) and reviewed by a human 👩
2025-11-25 11:29:11 +00:00
Danielle Maywood 82f525baf3 feat(coderd): add task prompt modification endpoint (#20811)
This PR adds the backend implementation for modifying task prompts. Part
of https://github.com/coder/internal/issues/1084

## Changes

- New `UpdateTaskPrompt` database query to update task prompts
- New PATCH `/api/v2/tasks/{task}/prompt` endpoint

## Notes

This is part 1 of a 2-part PR stack. The frontend UI will be added in a
follow-up PR based on this branch
(https://github.com/coder/coder/pull/20812).

---

🤖 PR was written by Claude Sonnet 4.5 Thinking using [Coder
Mux](https://github.com/coder/cmux) and reviewed by a human 👩
2025-11-25 11:13:32 +00:00
Spike Curtis afd40436f0 fix: mock Agent querying OS for listening ports in tests (#20842)
fixes https://github.com/coder/internal/issues/1123

We want to tests that ports are not included after they are no longer used, but this isn't safe on the real OS networking stack because there is no way to guarantee a port _won't_ be used. Instead, we introduce an interface and fake implementation for testing.

On order to leave the filtering logic in the test path, this PR also does some refactoring.

Caching logic is left in the real OS querying implementation and a new test case is added for it in this PR.
2025-11-25 14:25:24 +04:00
Danny Kopping 823009d9ea chore: document key scopes for OpenAI and Anthropic for aibridge (#20903)
Closes https://github.com/coder/internal/issues/1135

---------

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-25 11:33:07 +02:00
Danielle Maywood c12303f0b2 fix: allow agents to be created on dormant workspaces (#20909)
Closes https://github.com/coder/coder/issues/20711

We now allow agents to be created on dormant workspaces.

I've ran the test with and without the change. I've confirmed that -
without the fix - it triggers the "rbac: unauthorized" error.
2025-11-25 06:24:33 +00:00
Callum Styan 658e8c34a9 perf: improve performance of metricsAggregator path by reducing memory allocations (#20724)
Signed-off-by: Callum Styan <callumstyan@gmail.com>
2025-11-24 15:45:08 -08:00
Jake Howell ca560d36ce fix: remove inflight interceptions from aibridge returned values (#20852)
Addresses [`aibridge#54`](https://github.com/coder/aibridge/issues/54)

When querying against the values in the database for
`/api/experimental/aibridge/interceptions` we found strange behaviour
wherein there was interceptions that lacked prompting and other various
fields we want. Generally this was as a result of the data not actually
existing for these values (as they were inflight).

The simple solution to this was to hide them if they didn't exist. This
PR addresses that.

---------

Co-authored-by: Danny Kopping <danny@coder.com>
2025-11-25 10:23:39 +11:00
Jaayden Halko 6c2900f138 refactor: use a global tooltip provider with a consistent 100 millisecond delay duration (#20869)
Part 1 of 2

- this sets up the TooltipProvider for Storybook in preview.tsx and for
the app in App.tsx along with removing TooltipProvider in some of the
usages of Tooltip
- I tested existing components that haven't had the TooltipProvider
removed and they still function correctly. So should be fine until the
2nd PR to complete the migration.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-24 18:22:54 -05:00
DevCats f08cb2f059 feat: add documentation check workflow for pull requests (#20907)
<!--

If you have used AI to produce some or all of this PR, please ensure you
have read our [AI Contribution
guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING)
before submitting.

-->

Making this PR to test the workflow

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-24 17:05:41 -06:00
leo-wr-ps 3847f3b297 feat(helm): add priorityClassName support (#20678)
**Add priorityClassName support to Coder Helm chart**

Add coder.priorityClassName configuration to the Helm chart that allows
setting the pod's priorityClassName in the deployment

**Usage:**

```
coder:
  priorityClassName: high-priority
```

See: https://github.com/coder/coder/discussions/20676

---------

Co-authored-by: Rowan Smith <rowan@coder.com>
2025-11-25 09:06:33 +11:00
dependabot[bot] 42a24b7334 chore: bump google.golang.org/grpc from 1.76.0 to 1.77.0 (#20892)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from
1.76.0 to 1.77.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's
releases</a>.</em></p>
<blockquote>
<h2>Release 1.77.0</h2>
<h1>API Changes</h1>
<ul>
<li>mem: Replace the <code>Reader</code> interface with a struct for
better performance and maintainability. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8669">#8669</a>)</li>
</ul>
<h1>Behavior Changes</h1>
<ul>
<li>balancer/pickfirst: Remove support for the old
<code>pick_first</code> LB policy via the environment variable
<code>GRPC_EXPERIMENTAL_ENABLE_NEW_PICK_FIRST=false</code>. The new
<code>pick_first</code> has been the default since <code>v1.71.0</code>.
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/8672">#8672</a>)</li>
</ul>
<h1>Bug Fixes</h1>
<ul>
<li>xdsclient: Fix a race condition in the ADS stream implementation
that could result in <code>resource-not-found</code> errors, causing the
gRPC client channel to move to <code>TransientFailure</code>. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8605">#8605</a>)</li>
<li>client: Ignore HTTP status header for gRPC streams. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8548">#8548</a>)</li>
<li>client: Set a read deadline when closing a transport to prevent it
from blocking indefinitely on a broken connection. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8534">#8534</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/jgold2-stripe"><code>@​jgold2-stripe</code></a></li>
</ul>
</li>
<li>client: Fix a bug where default port 443 was not automatically added
to addresses without a specified port when sent to a proxy.
<ul>
<li>Setting environment variable
<code>GRPC_EXPERIMENTAL_ENABLE_DEFAULT_PORT_FOR_PROXY_TARGET=false</code>
disables this change; please file a bug if any problems are encountered
as we will remove this option soon. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8613">#8613</a>)</li>
</ul>
</li>
<li>balancer/pickfirst: Fix a bug where duplicate addresses were not
being ignored as intended. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8611">#8611</a>)</li>
<li>server: Fix a bug that caused overcounting of channelz metrics for
successful and failed streams. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8573">#8573</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/hugehoo"><code>@​hugehoo</code></a></li>
</ul>
</li>
<li>balancer/pickfirst: When configured, shuffle addresses in resolver
updates that lack endpoints. Since gRPC automatically adds endpoints to
resolver updates, this bug only affects custom LB policies that delegate
to <code>pick_first</code> but don't set endpoints. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8610">#8610</a>)</li>
<li>mem: Clear large buffers before re-using. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8670">#8670</a>)</li>
</ul>
<h1>Performance Improvements</h1>
<ul>
<li>transport: Reduce heap allocations to reduce time spent in garbage
collection. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8624">#8624</a>,
<a
href="https://redirect.github.com/grpc/grpc-go/issues/8630">#8630</a>,
<a
href="https://redirect.github.com/grpc/grpc-go/issues/8639">#8639</a>,
<a
href="https://redirect.github.com/grpc/grpc-go/issues/8668">#8668</a>)</li>
<li>transport: Avoid copies when reading and writing Data frames. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8657">#8657</a>,
<a
href="https://redirect.github.com/grpc/grpc-go/issues/8667">#8667</a>)</li>
<li>mem: Avoid clearing newly allocated buffers. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8670">#8670</a>)</li>
</ul>
<h1>New Features</h1>
<ul>
<li>outlierdetection: Add metrics specified in <a
href="https://github.com/grpc/proposal/blob/master/A91-outlier-detection-metrics.md">gRFC
A91</a>. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8644">#8644</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/davinci26"><code>@​davinci26</code></a>, <a
href="https://github.com/PardhuKonakanchi"><code>@​PardhuKonakanchi</code></a></li>
</ul>
</li>
<li>stats/opentelemetry: Add support for optional label
<code>grpc.lb.backend_service</code> in per-call metrics (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8637">#8637</a>)</li>
<li>xds: Add support for JWT Call Credentials as specified in <a
href="https://github.com/grpc/proposal/blob/master/A97-xds-jwt-call-creds.md">gRFC
A97</a>. Set environment variable
<code>GRPC_EXPERIMENTAL_XDS_BOOTSTRAP_CALL_CREDS=true</code> to enable
this feature. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8536">#8536</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/dimpavloff"><code>@​dimpavloff</code></a></li>
</ul>
</li>
<li>experimental/stats: Add support for up/down counters. (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8581">#8581</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/grpc/grpc-go/commit/805b1f88c5fb9419e3837c72e1deb9c2ec677ffe"><code>805b1f8</code></a>
Change version to 1.77.0 (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8677">#8677</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/ea7b66e1caa21b242b035bc4f598edb82093877f"><code>ea7b66e</code></a>
Cherrypick <a
href="https://redirect.github.com/grpc/grpc-go/issues/8702">#8702</a> to
v1.77.x (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8709">#8709</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/cadae08d5f37d60083091c103a89d5566b7ae34e"><code>cadae08</code></a>
Cherry-pick <a
href="https://redirect.github.com/grpc/grpc-go/issues/8536">#8536</a> to
v1.77.x (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8691">#8691</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/4288cfc5aba43fa11ad9b769f58b193b78f76a3b"><code>4288cfc</code></a>
Cherrypick <a
href="https://redirect.github.com/grpc/grpc-go/issues/8657">#8657</a>
and <a
href="https://redirect.github.com/grpc/grpc-go/issues/8667">#8667</a> to
v1.77.x (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8690">#8690</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/f959da611763ff733f7fb6b4b04c0f796d0fa441"><code>f959da6</code></a>
transport: Reduce heap allocations (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8668">#8668</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/0d49384b60894f29d2da20f7f72987aed4fbb229"><code>0d49384</code></a>
deps: update all dependencies (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8673">#8673</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/e3e142d0e32ff4e500ca140dc5eaed66adac9bfd"><code>e3e142d</code></a>
pickfirst: Remove old pickfirst (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8672">#8672</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/254ab1095e9f4179cebd36517bfb7e61b623e509"><code>254ab10</code></a>
documentation: fix typos in benchmark and auth docs (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8674">#8674</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/2d56bdadb11058f67c48e3c837fcf4a487e15346"><code>2d56bda</code></a>
mem: Remove Reader interface and export the concrete struct (<a
href="https://redirect.github.com/grpc/grpc-go/issues/8669">#8669</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/8ab0c8214a28222821a1a761996b76f9bfa6aca7"><code>8ab0c82</code></a>
mem: Avoid clearing new buffers and clear buffers from simpleBufferPools
(<a
href="https://redirect.github.com/grpc/grpc-go/issues/8670">#8670</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/grpc/grpc-go/compare/v1.76.0...v1.77.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.76.0&new-version=1.77.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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 18:21:45 +00:00
dependabot[bot] ba242b5e77 chore: bump github.com/prometheus/common from 0.65.0 to 0.67.4 (#20890)
[//]: # (dependabot-start)
⚠️  **Dependabot is rebasing this PR** ⚠️ 

Rebasing might not happen immediately, so don't worry if this takes some
time.

Note: if you make any changes to this PR yourself, they will take
precedence over the rebase.

---

[//]: # (dependabot-end)

Bumps
[github.com/prometheus/common](https://github.com/prometheus/common)
from 0.65.0 to 0.67.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/prometheus/common/releases">github.com/prometheus/common's
releases</a>.</em></p>
<blockquote>
<h2>v0.67.4 / 2025-11-18</h2>
<h2>What's Changed</h2>
<ul>
<li>chore: clean up golangci-lint configuration by <a
href="https://github.com/mmorel-35"><code>@​mmorel-35</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/782">prometheus/common#782</a></li>
<li>chore: 'omitempty' to Oauth2 fields with type Secret to avoid
requiring them by <a
href="https://github.com/JorTurFer"><code>@​JorTurFer</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/864">prometheus/common#864</a></li>
<li>chore: Add omitempty tag to all config fields by <a
href="https://github.com/JorTurFer"><code>@​JorTurFer</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/865">prometheus/common#865</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.67.3...v0.67.4">https://github.com/prometheus/common/compare/v0.67.3...v0.67.4</a></p>
<h2>v0.67.3 / 2025-11-18</h2>
<h2>What's Changed</h2>
<ul>
<li>Support JWT Profile for Authorization Grant (RFC 7523 3.1) by <a
href="https://github.com/JorTurFer"><code>@​JorTurFer</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/862">prometheus/common#862</a></li>
<li>Config: remove outdated comment about HTTP/2 issues by <a
href="https://github.com/bboreham"><code>@​bboreham</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/863">prometheus/common#863</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/JorTurFer"><code>@​JorTurFer</code></a>
made their first contribution in <a
href="https://redirect.github.com/prometheus/common/pull/862">prometheus/common#862</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.67.2...v0.67.3">https://github.com/prometheus/common/compare/v0.67.2...v0.67.3</a></p>
<h2>v0.67.2 / 2025-10-28</h2>
<h2>What's Changed</h2>
<ul>
<li>config: Fix panic in <code>tlsRoundTripper</code> when CA file is
absent by <a href="https://github.com/ndk"><code>@​ndk</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/792">prometheus/common#792</a></li>
<li>Cleanup linting issues by <a
href="https://github.com/SuperQ"><code>@​SuperQ</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/860">prometheus/common#860</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/ndk"><code>@​ndk</code></a> made their
first contribution in <a
href="https://redirect.github.com/prometheus/common/pull/792">prometheus/common#792</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.67.1...v0.67.2">https://github.com/prometheus/common/compare/v0.67.1...v0.67.2</a></p>
<h2>v0.67.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix Go case-insensitive file name collision by <a
href="https://github.com/SuperQ"><code>@​SuperQ</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/853">prometheus/common#853</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.67.0...v0.67.1">https://github.com/prometheus/common/compare/v0.67.0...v0.67.1</a></p>
<h2>v0.67.0 / 2025-10-07</h2>
<h2>What's Changed</h2>
<ul>
<li>Create CHANGELOG.md for easier communication of library changes,
especially possible breaking changes. by <a
href="https://github.com/ywwg"><code>@​ywwg</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/833">prometheus/common#833</a></li>
<li>model: New test for validation with dots by <a
href="https://github.com/m1k1o"><code>@​m1k1o</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/759">prometheus/common#759</a></li>
<li>expfmt: document NewTextParser as required by <a
href="https://github.com/burgerdev"><code>@​burgerdev</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/842">prometheus/common#842</a></li>
<li>expfmt: Add support for float histograms and gauge histograms by <a
href="https://github.com/beorn7"><code>@​beorn7</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/843">prometheus/common#843</a></li>
<li>Updated minimum Go version to 1.24.0, updated Go dependecies by <a
href="https://github.com/SuperQ"><code>@​SuperQ</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/849">prometheus/common#849</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/m1k1o"><code>@​m1k1o</code></a> made
their first contribution in <a
href="https://redirect.github.com/prometheus/common/pull/759">prometheus/common#759</a></li>
<li><a href="https://github.com/burgerdev"><code>@​burgerdev</code></a>
made their first contribution in <a
href="https://redirect.github.com/prometheus/common/pull/842">prometheus/common#842</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.66.1...v0.67.0">https://github.com/prometheus/common/compare/v0.66.1...v0.67.0</a></p>
<h2>v0.66.1</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/prometheus/common/blob/main/CHANGELOG.md">github.com/prometheus/common's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>main / unreleased</h2>
<h3>What's Changed</h3>
<h2>v0.67.2 / 2025-10-28</h2>
<h2>What's Changed</h2>
<ul>
<li>config: Fix panic in <code>tlsRoundTripper</code> when CA file is
absent by <a href="https://github.com/ndk"><code>@​ndk</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/792">prometheus/common#792</a></li>
<li>Cleanup linting issues by <a
href="https://github.com/SuperQ"><code>@​SuperQ</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/860">prometheus/common#860</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/ndk"><code>@​ndk</code></a> made their
first contribution in <a
href="https://redirect.github.com/prometheus/common/pull/792">prometheus/common#792</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.67.1...v0.67.2">https://github.com/prometheus/common/compare/v0.67.1...v0.67.2</a></p>
<h2>v0.67.1 / 2025-10-07</h2>
<h2>What's Changed</h2>
<ul>
<li>Remove VERSION file to avoid Go conflict error in <a
href="https://redirect.github.com/prometheus/common/pull/853">prometheus/common#853</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.67.0...v0.67.1">https://github.com/prometheus/common/compare/v0.67.0...v0.67.1</a></p>
<h2>v0.67.0 / 2025-10-07</h2>
<h2>What's Changed</h2>
<ul>
<li>Create CHANGELOG.md for easier communication of library changes,
especially possible breaking changes. by <a
href="https://github.com/ywwg"><code>@​ywwg</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/833">prometheus/common#833</a></li>
<li>model: New test for validation with dots by <a
href="https://github.com/m1k1o"><code>@​m1k1o</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/759">prometheus/common#759</a></li>
<li>expfmt: document NewTextParser as required by <a
href="https://github.com/burgerdev"><code>@​burgerdev</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/842">prometheus/common#842</a></li>
<li>expfmt: Add support for float histograms and gauge histograms by <a
href="https://github.com/beorn7"><code>@​beorn7</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/843">prometheus/common#843</a></li>
<li>Updated minimum Go version to 1.24.0, updated Go dependecies by <a
href="https://github.com/SuperQ"><code>@​SuperQ</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/849">prometheus/common#849</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/m1k1o"><code>@​m1k1o</code></a> made
their first contribution in <a
href="https://redirect.github.com/prometheus/common/pull/759">prometheus/common#759</a></li>
<li><a href="https://github.com/burgerdev"><code>@​burgerdev</code></a>
made their first contribution in <a
href="https://redirect.github.com/prometheus/common/pull/842">prometheus/common#842</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v0.66.1...v0.67.0">https://github.com/prometheus/common/compare/v0.66.1...v0.67.0</a></p>
<h2>v0.66.1 / 2025-09-05</h2>
<p>This release has no functional changes, it just drops the
dependencies <code>github.com/grafana/regexp</code> and
<code>go.uber.org/atomic</code> and replaces
<code>gopkg.in/yaml.v2</code> with <code>go.yaml.in/yaml/v2</code> (a
drop-in replacement).</p>
<h3>What's Changed</h3>
<ul>
<li>Revert &quot;Use github.com/grafana/regexp instead of regexp&quot;
by <a href="https://github.com/aknuds1"><code>@​aknuds1</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/835">prometheus/common#835</a></li>
<li>Move to supported version of yaml parser by <a
href="https://github.com/dims"><code>@​dims</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/834">prometheus/common#834</a></li>
<li>Revert &quot;Use go.uber.org/atomic instead of sync/atomic (<a
href="https://redirect.github.com/prometheus/common/issues/825">#825</a>)&quot;
by <a href="https://github.com/aknuds1"><code>@​aknuds1</code></a> in <a
href="https://redirect.github.com/prometheus/common/pull/838">prometheus/common#838</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/prometheus/common/compare/v1.20.99...v0.66.1">https://github.com/prometheus/common/compare/v1.20.99...v0.66.1</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/prometheus/common/commit/d80d8544703e59a080a204b6f7429ac6561fb24f"><code>d80d854</code></a>
chore: Add omitempty tag to all config fields (<a
href="https://redirect.github.com/prometheus/common/issues/865">#865</a>)</li>
<li><a
href="https://github.com/prometheus/common/commit/04686b2cfc6804598d99b86070135f9266998c59"><code>04686b2</code></a>
chore: 'omitempty' to Oauth2 fields with type Secret to avoid requiring
them ...</li>
<li><a
href="https://github.com/prometheus/common/commit/0b2fbf31f0e2c21d9e1a4e51e698188fae258cb2"><code>0b2fbf3</code></a>
chore: clean up golangci-lint configuration (<a
href="https://redirect.github.com/prometheus/common/issues/782">#782</a>)</li>
<li><a
href="https://github.com/prometheus/common/commit/b2cdb0785c1498399587cb0bf42aa960d810633a"><code>b2cdb07</code></a>
Merge pull request <a
href="https://redirect.github.com/prometheus/common/issues/863">#863</a>
from prometheus/remove-http2-comment</li>
<li><a
href="https://github.com/prometheus/common/commit/cd1ab56cc1e1d41dbc286d2e501e26515400b9be"><code>cd1ab56</code></a>
Config: remove outdated comment about HTTP/2 issues</li>
<li><a
href="https://github.com/prometheus/common/commit/f4c0aea59fa97a7627730e65cb2e625ec9fc45cf"><code>f4c0aea</code></a>
Support JWT Profile for Authorization Grant (RFC 7523 3.1) (<a
href="https://redirect.github.com/prometheus/common/issues/862">#862</a>)</li>
<li><a
href="https://github.com/prometheus/common/commit/594f4d4a984eb5f1ca8f0983f8b1790e77a5a725"><code>594f4d4</code></a>
Merge pull request <a
href="https://redirect.github.com/prometheus/common/issues/861">#861</a>
from prometheus/beorn7/version</li>
<li><a
href="https://github.com/prometheus/common/commit/440c1a30a0315f2ca0dba99fd7fffb288a3e898b"><code>440c1a3</code></a>
Cut v0.67.2</li>
<li><a
href="https://github.com/prometheus/common/commit/acb18736bed74c218ee4023ed1e0e36cf2dd1612"><code>acb1873</code></a>
Merge pull request <a
href="https://redirect.github.com/prometheus/common/issues/860">#860</a>
from prometheus/superq/linting</li>
<li><a
href="https://github.com/prometheus/common/commit/1e323394d0ceaccda49f263dc81456e33af4263b"><code>1e32339</code></a>
Cleanup linting issues</li>
<li>Additional commits viewable in <a
href="https://github.com/prometheus/common/compare/v0.65.0...v0.67.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/prometheus/common&package-manager=go_modules&previous-version=0.65.0&new-version=0.67.4)](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 this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 17:10:01 +00:00
Steven Masley 0c43789f3a test: move TestConvertStateGolden to only linux + mac (#20901)
Windows runners are flaky for golden files
closes https://github.com/coder/internal/issues/1141
2025-11-24 10:25:08 -06:00
Steven Masley cefe07d074 feat: purge expired api keys in dbpurge (#20863)
closes https://github.com/coder/coder/issues/19889

This is in response to a migration in v2.27 that takes very long on deployments with large `api_key` tables.
2025-11-24 10:24:32 -06:00
Danny Kopping c6631e1e50 feat: expose aibridged metrics (#20865)
Upgrades `coder/aibridge` to v0.2.0 which includes
https://github.com/coder/aibridge/pull/62.

Creates a `prometheus.Registerer` with a prefix `coder_aibridged_` and
passes that along to coder/aibridge which actually exposes the metrics.

Also includes a side-effect of a change described in
https://github.com/coder/aibridge/pull/62#discussion_r2550017470.

---------

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-24 18:16:06 +02:00
438 changed files with 19835 additions and 10201 deletions
+126
View File
@@ -0,0 +1,126 @@
# Coder Architecture
This document provides an overview of Coder's architecture and core systems.
## What is Coder?
Coder is a platform for creating, managing, and using remote development environments (also known as Cloud Development Environments or CDEs). It leverages Terraform to define and provision these environments, which are referred to as "workspaces" within the project. The system is designed to be extensible, secure, and provide developers with a seamless remote development experience.
## Core Architecture
The heart of Coder is a control plane that orchestrates the creation and management of workspaces. This control plane interacts with separate Provisioner processes over gRPC to handle workspace builds. The Provisioners consume workspace definitions and use Terraform to create the actual infrastructure.
The CLI package serves dual purposes - it can be used to launch the control plane itself and also provides client functionality for users to interact with an existing control plane instance. All user-facing frontend code is developed in TypeScript using React and lives in the `site/` directory.
The database layer uses PostgreSQL with SQLC for generating type-safe database code. Database migrations are carefully managed to ensure both forward and backward compatibility through paired `.up.sql` and `.down.sql` files.
## API Design
Coder's API architecture combines REST and gRPC approaches. The REST API is defined in `coderd/coderd.go` and uses Chi for HTTP routing. This provides the primary interface for the frontend and external integrations.
Internal communication with Provisioners occurs over gRPC, with service definitions maintained in `.proto` files. This separation allows for efficient binary communication with the components responsible for infrastructure management while providing a standard REST interface for human-facing applications.
## Network Architecture
Coder implements a secure networking layer based on Tailscale's Wireguard implementation. The `tailnet` package provides connectivity between workspace agents and clients through DERP (Designated Encrypted Relay for Packets) servers when direct connections aren't possible. This creates a secure overlay network allowing access to workspaces regardless of network topology, firewalls, or NAT configurations.
### Tailnet and DERP System
The networking system has three key components:
1. **Tailnet**: An overlay network implemented in the `tailnet` package that provides secure, end-to-end encrypted connections between clients, the Coder server, and workspace agents.
2. **DERP Servers**: These relay traffic when direct connections aren't possible. Coder provides several options:
- A built-in DERP server that runs on the Coder control plane
- Integration with Tailscale's global DERP infrastructure
- Support for custom DERP servers for lower latency or offline deployments
3. **Direct Connections**: When possible, the system establishes peer-to-peer connections between clients and workspaces using STUN for NAT traversal. This requires both endpoints to send UDP traffic on ephemeral ports.
### Workspace Proxies
Workspace proxies (in the Enterprise edition) provide regional relay points for browser-based connections, reducing latency for geo-distributed teams. Key characteristics:
- Deployed as independent servers that authenticate with the Coder control plane
- Relay connections for SSH, workspace apps, port forwarding, and web terminals
- Do not make direct database connections
- Managed through the `coder wsproxy` commands
- Implemented primarily in the `enterprise/wsproxy/` package
## Agent System
The workspace agent runs within each provisioned workspace and provides core functionality including:
- SSH access to workspaces via the `agentssh` package
- Port forwarding
- Terminal connectivity via the `pty` package for pseudo-terminal support
- Application serving
- Healthcheck monitoring
- Resource usage reporting
Agents communicate with the control plane using the tailnet system and authenticate using secure tokens.
## Workspace Applications
Workspace applications (or "apps") provide browser-based access to services running within workspaces. The system supports:
- HTTP(S) and WebSocket connections
- Path-based or subdomain-based access URLs
- Health checks to monitor application availability
- Different sharing levels (owner-only, authenticated users, or public)
- Custom icons and display settings
The implementation is primarily in the `coderd/workspaceapps/` directory with components for URL generation, proxying connections, and managing application state.
## Implementation Details
The project structure separates frontend and backend concerns. React components and pages are organized in the `site/src/` directory, with Jest used for testing. The backend is primarily written in Go, with a strong emphasis on error handling patterns and test coverage.
Database interactions are carefully managed through migrations in `coderd/database/migrations/` and queries in `coderd/database/queries/`. All new queries require proper database authorization (dbauthz) implementation to ensure that only users with appropriate permissions can access specific resources.
## Authorization System
The database authorization (dbauthz) system enforces fine-grained access control across all database operations. It uses role-based access control (RBAC) to validate user permissions before executing database operations. The `dbauthz` package wraps the database store and performs authorization checks before returning data. All database operations must pass through this layer to ensure security.
## Testing Framework
The codebase has a comprehensive testing approach with several key components:
1. **Parallel Testing**: All tests must use `t.Parallel()` to run concurrently, which improves test suite performance and helps identify race conditions.
2. **coderdtest Package**: This package in `coderd/coderdtest/` provides utilities for creating test instances of the Coder server, setting up test users and workspaces, and mocking external components.
3. **Integration Tests**: Tests often span multiple components to verify system behavior, such as template creation, workspace provisioning, and agent connectivity.
4. **Enterprise Testing**: Enterprise features have dedicated test utilities in the `coderdenttest` package.
## Open Source and Enterprise Components
The repository contains both open source and enterprise components:
- Enterprise code lives primarily in the `enterprise/` directory
- Enterprise features focus on governance, scalability (high availability), and advanced deployment options like workspace proxies
- The boundary between open source and enterprise is managed through a licensing system
- The same core codebase supports both editions, with enterprise features conditionally enabled
## Development Philosophy
Coder emphasizes clear error handling, with specific patterns required:
- Concise error messages that avoid phrases like "failed to"
- Wrapping errors with `%w` to maintain error chains
- Using sentinel errors with the "err" prefix (e.g., `errNotFound`)
All tests should run in parallel using `t.Parallel()` to ensure efficient testing and expose potential race conditions. The codebase is rigorously linted with golangci-lint to maintain consistent code quality.
Git contributions follow a standard format with commit messages structured as `type: <message>`, where type is one of `feat`, `fix`, or `chore`.
## Development Workflow
Development can be initiated using `scripts/develop.sh` to start the application after making changes. Database schema updates should be performed through the migration system using `create_migration.sh <name>` to generate migration files, with each `.up.sql` migration paired with a corresponding `.down.sql` that properly reverts all changes.
If the development database gets into a bad state, it can be completely reset by removing the PostgreSQL data directory with `rm -rf .coderv2/postgres`. This will destroy all data in the development database, requiring you to recreate any test users, templates, or workspaces after restarting the application.
Code generation for the database layer uses `coderd/database/generate.sh`, and developers should refer to `sqlc.yaml` for the appropriate style and patterns to follow when creating new queries or tables.
The focus should always be on maintaining security through proper database authorization, clean error handling, and comprehensive test coverage to ensure the platform remains robust and reliable.
-124
View File
@@ -1,124 +0,0 @@
# Cursor Rules
This project is called "Coder" - an application for managing remote development environments.
Coder provides a platform for creating, managing, and using remote development environments (also known as Cloud Development Environments or CDEs). It leverages Terraform to define and provision these environments, which are referred to as "workspaces" within the project. The system is designed to be extensible, secure, and provide developers with a seamless remote development experience.
## Core Architecture
The heart of Coder is a control plane that orchestrates the creation and management of workspaces. This control plane interacts with separate Provisioner processes over gRPC to handle workspace builds. The Provisioners consume workspace definitions and use Terraform to create the actual infrastructure.
The CLI package serves dual purposes - it can be used to launch the control plane itself and also provides client functionality for users to interact with an existing control plane instance. All user-facing frontend code is developed in TypeScript using React and lives in the `site/` directory.
The database layer uses PostgreSQL with SQLC for generating type-safe database code. Database migrations are carefully managed to ensure both forward and backward compatibility through paired `.up.sql` and `.down.sql` files.
## API Design
Coder's API architecture combines REST and gRPC approaches. The REST API is defined in `coderd/coderd.go` and uses Chi for HTTP routing. This provides the primary interface for the frontend and external integrations.
Internal communication with Provisioners occurs over gRPC, with service definitions maintained in `.proto` files. This separation allows for efficient binary communication with the components responsible for infrastructure management while providing a standard REST interface for human-facing applications.
## Network Architecture
Coder implements a secure networking layer based on Tailscale's Wireguard implementation. The `tailnet` package provides connectivity between workspace agents and clients through DERP (Designated Encrypted Relay for Packets) servers when direct connections aren't possible. This creates a secure overlay network allowing access to workspaces regardless of network topology, firewalls, or NAT configurations.
### Tailnet and DERP System
The networking system has three key components:
1. **Tailnet**: An overlay network implemented in the `tailnet` package that provides secure, end-to-end encrypted connections between clients, the Coder server, and workspace agents.
2. **DERP Servers**: These relay traffic when direct connections aren't possible. Coder provides several options:
- A built-in DERP server that runs on the Coder control plane
- Integration with Tailscale's global DERP infrastructure
- Support for custom DERP servers for lower latency or offline deployments
3. **Direct Connections**: When possible, the system establishes peer-to-peer connections between clients and workspaces using STUN for NAT traversal. This requires both endpoints to send UDP traffic on ephemeral ports.
### Workspace Proxies
Workspace proxies (in the Enterprise edition) provide regional relay points for browser-based connections, reducing latency for geo-distributed teams. Key characteristics:
- Deployed as independent servers that authenticate with the Coder control plane
- Relay connections for SSH, workspace apps, port forwarding, and web terminals
- Do not make direct database connections
- Managed through the `coder wsproxy` commands
- Implemented primarily in the `enterprise/wsproxy/` package
## Agent System
The workspace agent runs within each provisioned workspace and provides core functionality including:
- SSH access to workspaces via the `agentssh` package
- Port forwarding
- Terminal connectivity via the `pty` package for pseudo-terminal support
- Application serving
- Healthcheck monitoring
- Resource usage reporting
Agents communicate with the control plane using the tailnet system and authenticate using secure tokens.
## Workspace Applications
Workspace applications (or "apps") provide browser-based access to services running within workspaces. The system supports:
- HTTP(S) and WebSocket connections
- Path-based or subdomain-based access URLs
- Health checks to monitor application availability
- Different sharing levels (owner-only, authenticated users, or public)
- Custom icons and display settings
The implementation is primarily in the `coderd/workspaceapps/` directory with components for URL generation, proxying connections, and managing application state.
## Implementation Details
The project structure separates frontend and backend concerns. React components and pages are organized in the `site/src/` directory, with Jest used for testing. The backend is primarily written in Go, with a strong emphasis on error handling patterns and test coverage.
Database interactions are carefully managed through migrations in `coderd/database/migrations/` and queries in `coderd/database/queries/`. All new queries require proper database authorization (dbauthz) implementation to ensure that only users with appropriate permissions can access specific resources.
## Authorization System
The database authorization (dbauthz) system enforces fine-grained access control across all database operations. It uses role-based access control (RBAC) to validate user permissions before executing database operations. The `dbauthz` package wraps the database store and performs authorization checks before returning data. All database operations must pass through this layer to ensure security.
## Testing Framework
The codebase has a comprehensive testing approach with several key components:
1. **Parallel Testing**: All tests must use `t.Parallel()` to run concurrently, which improves test suite performance and helps identify race conditions.
2. **coderdtest Package**: This package in `coderd/coderdtest/` provides utilities for creating test instances of the Coder server, setting up test users and workspaces, and mocking external components.
3. **Integration Tests**: Tests often span multiple components to verify system behavior, such as template creation, workspace provisioning, and agent connectivity.
4. **Enterprise Testing**: Enterprise features have dedicated test utilities in the `coderdenttest` package.
## Open Source and Enterprise Components
The repository contains both open source and enterprise components:
- Enterprise code lives primarily in the `enterprise/` directory
- Enterprise features focus on governance, scalability (high availability), and advanced deployment options like workspace proxies
- The boundary between open source and enterprise is managed through a licensing system
- The same core codebase supports both editions, with enterprise features conditionally enabled
## Development Philosophy
Coder emphasizes clear error handling, with specific patterns required:
- Concise error messages that avoid phrases like "failed to"
- Wrapping errors with `%w` to maintain error chains
- Using sentinel errors with the "err" prefix (e.g., `errNotFound`)
All tests should run in parallel using `t.Parallel()` to ensure efficient testing and expose potential race conditions. The codebase is rigorously linted with golangci-lint to maintain consistent code quality.
Git contributions follow a standard format with commit messages structured as `type: <message>`, where type is one of `feat`, `fix`, or `chore`.
## Development Workflow
Development can be initiated using `scripts/develop.sh` to start the application after making changes. Database schema updates should be performed through the migration system using `create_migration.sh <name>` to generate migration files, with each `.up.sql` migration paired with a corresponding `.down.sql` that properly reverts all changes.
If the development database gets into a bad state, it can be completely reset by removing the PostgreSQL data directory with `rm -rf .coderv2/postgres`. This will destroy all data in the development database, requiring you to recreate any test users, templates, or workspaces after restarting the application.
Code generation for the database layer uses `coderd/database/generate.sh`, and developers should refer to `sqlc.yaml` for the appropriate style and patterns to follow when creating new queries or tables.
The focus should always be on maintaining security through proper database authorization, clean error handling, and comprehensive test coverage to ensure the platform remains robust and reliable.
+1
View File
@@ -0,0 +1 @@
AGENTS.md
+1 -1
View File
@@ -27,7 +27,7 @@ ignorePatterns:
- pattern: "splunk.com"
- pattern: "stackoverflow.com/questions"
- pattern: "developer.hashicorp.com/terraform/language"
- pattern: "platform.openai.com/docs/api-reference"
- pattern: "platform.openai.com"
- pattern: "api.openai.com"
aliveStatusCodes:
- 200
+6 -4
View File
@@ -6,6 +6,8 @@ updates:
interval: "weekly"
time: "06:00"
timezone: "America/Chicago"
cooldown:
default-days: 7
labels: []
commit-message:
prefix: "ci"
@@ -68,8 +70,8 @@ updates:
interval: "monthly"
time: "06:00"
timezone: "America/Chicago"
reviewers:
- "coder/ts"
cooldown:
default-days: 7
commit-message:
prefix: "chore"
labels: []
@@ -119,9 +121,9 @@ updates:
commit-message:
prefix: "chore"
groups:
coder:
coder-modules:
patterns:
- "registry.coder.com/coder/*/coder"
- "coder/*/coder"
labels: []
ignore:
- dependency-name: "*"
-26
View File
@@ -1,26 +0,0 @@
name: API Docs Linter
on:
push:
branches:
- main
pull_request:
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq
- name: Run API docs linter
run: ./scripts/api-docs-linter.sh
+20 -20
View File
@@ -40,7 +40,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -124,7 +124,7 @@ jobs:
# runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
# steps:
# - name: Checkout
# uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
# uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
# with:
# fetch-depth: 1
# # See: https://github.com/stefanzweifel/git-auto-commit-action?tab=readme-ov-file#commits-made-by-this-action-do-not-trigger-new-workflow-runs
@@ -162,7 +162,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -191,7 +191,7 @@ jobs:
# Check for any typos
- name: Check for typos
uses: crate-ci/typos@626c4bedb751ce0b7f03262ca97ddda9a076ae1c # v1.39.2
uses: crate-ci/typos@2d0ce569feab1f8752f1dde43cc2f2aa53236e06 # v1.40.0
with:
config: .github/workflows/typos.toml
@@ -240,7 +240,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -297,7 +297,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -369,7 +369,7 @@ jobs:
uses: coder/setup-ramdisk-action@e1100847ab2d7bcd9d14bcda8f2d1b0f07b36f1b # v0.1.0
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -537,7 +537,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -586,7 +586,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -646,7 +646,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -673,7 +673,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -706,7 +706,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
@@ -786,7 +786,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
# 👇 Ensures Chromatic can read your full git history
fetch-depth: 0
@@ -802,7 +802,7 @@ jobs:
# the check to pass. This is desired in PRs, but not in mainline.
- name: Publish to Chromatic (non-mainline)
if: github.ref != 'refs/heads/main' && github.repository_owner == 'coder'
uses: chromaui/action@ac86f2ff0a458ffbce7b40698abd44c0fa34d4b6 # v13.3.3
uses: chromaui/action@4c20b95e9d3209ecfdf9cd6aace6bbde71ba1694 # v13.3.4
env:
NODE_OPTIONS: "--max_old_space_size=4096"
STORYBOOK: true
@@ -834,7 +834,7 @@ jobs:
# infinitely "in progress" in mainline unless we re-review each build.
- name: Publish to Chromatic (mainline)
if: github.ref == 'refs/heads/main' && github.repository_owner == 'coder'
uses: chromaui/action@ac86f2ff0a458ffbce7b40698abd44c0fa34d4b6 # v13.3.3
uses: chromaui/action@4c20b95e9d3209ecfdf9cd6aace6bbde71ba1694 # v13.3.4
env:
NODE_OPTIONS: "--max_old_space_size=4096"
STORYBOOK: true
@@ -867,7 +867,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
# 0 is required here for version.sh to work.
fetch-depth: 0
@@ -971,7 +971,7 @@ jobs:
steps:
# Harden Runner doesn't work on macOS
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -1058,7 +1058,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -1113,7 +1113,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -1510,7 +1510,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
+9 -1
View File
@@ -28,6 +28,7 @@ jobs:
github-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Approve the PR
if: steps.metadata.outputs.package-ecosystem != 'github-actions'
run: |
echo "Approving $PR_URL"
gh pr review --approve "$PR_URL"
@@ -36,6 +37,7 @@ jobs:
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Enable auto-merge
if: steps.metadata.outputs.package-ecosystem != 'github-actions'
run: |
echo "Enabling auto-merge for $PR_URL"
gh pr merge --auto --squash "$PR_URL"
@@ -45,6 +47,11 @@ jobs:
- name: Send Slack notification
run: |
if [ "$PACKAGE_ECOSYSTEM" = "github-actions" ]; then
STATUS_TEXT=":pr-opened: Dependabot opened PR #${PR_NUMBER} (GitHub Actions changes are not auto-merged)"
else
STATUS_TEXT=":pr-merged: Auto merge enabled for Dependabot PR #${PR_NUMBER}"
fi
curl -X POST -H 'Content-type: application/json' \
--data '{
"username": "dependabot",
@@ -54,7 +61,7 @@ jobs:
"type": "header",
"text": {
"type": "plain_text",
"text": ":pr-merged: Auto merge enabled for Dependabot PR #'"${PR_NUMBER}"'",
"text": "'"${STATUS_TEXT}"'",
"emoji": true
}
},
@@ -84,6 +91,7 @@ jobs:
}' "${{ secrets.DEPENDABOT_PRS_SLACK_WEBHOOK }}"
env:
SLACK_WEBHOOK: ${{ secrets.DEPENDABOT_PRS_SLACK_WEBHOOK }}
PACKAGE_ECOSYSTEM: ${{ steps.metadata.outputs.package-ecosystem }}
PR_NUMBER: ${{ github.event.pull_request.number }}
PR_TITLE: ${{ github.event.pull_request.title }}
PR_URL: ${{ github.event.pull_request.html_url }}
+4 -4
View File
@@ -41,7 +41,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -70,7 +70,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -92,7 +92,7 @@ jobs:
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1
- name: Set up Flux CLI
uses: fluxcd/flux2/action@b6e76ca2534f76dcb8dd94fb057cdfa923c3b641 # v2.7.3
uses: fluxcd/flux2/action@8454b02a32e48d775b9f563cb51fdcb1787b5b93 # v2.7.5
with:
# Keep this and the github action up to date with the version of flux installed in dogfood cluster
version: "2.7.0"
@@ -151,7 +151,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
+205
View File
@@ -0,0 +1,205 @@
# This workflow checks if a PR requires documentation updates.
# It creates a Coder Task that uses AI to analyze the PR changes,
# search existing docs, and comment with recommendations.
#
# Triggered by: Adding the "doc-check" label to a PR, or manual dispatch.
name: AI Documentation Check
on:
pull_request:
types:
- labeled
workflow_dispatch:
inputs:
pr_url:
description: "Pull Request URL to check"
required: true
type: string
template_preset:
description: "Template preset to use"
required: false
default: ""
type: string
jobs:
doc-check:
name: Analyze PR for Documentation Updates Needed
runs-on: ubuntu-latest
if: |
(github.event.label.name == 'doc-check' || github.event_name == 'workflow_dispatch') &&
(github.event.pull_request.draft == false || github.event_name == 'workflow_dispatch')
timeout-minutes: 30
env:
CODER_URL: ${{ secrets.DOC_CHECK_CODER_URL }}
CODER_SESSION_TOKEN: ${{ secrets.DOC_CHECK_CODER_SESSION_TOKEN }}
permissions:
contents: read
pull-requests: write
actions: write
steps:
- name: Determine PR Context
id: determine-context
env:
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_EVENT_PR_HTML_URL: ${{ github.event.pull_request.html_url }}
GITHUB_EVENT_PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_EVENT_SENDER_ID: ${{ github.event.sender.id }}
GITHUB_EVENT_SENDER_LOGIN: ${{ github.event.sender.login }}
INPUTS_PR_URL: ${{ inputs.pr_url }}
INPUTS_TEMPLATE_PRESET: ${{ inputs.template_preset || '' }}
GH_TOKEN: ${{ github.token }}
run: |
echo "Using template preset: ${INPUTS_TEMPLATE_PRESET}"
echo "template_preset=${INPUTS_TEMPLATE_PRESET}" >> "${GITHUB_OUTPUT}"
# For workflow_dispatch, use the provided PR URL
if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
if ! GITHUB_USER_ID=$(gh api "users/${GITHUB_ACTOR}" --jq '.id'); then
echo "::error::Failed to get GitHub user ID for actor ${GITHUB_ACTOR}"
exit 1
fi
echo "Using workflow_dispatch actor: ${GITHUB_ACTOR} (ID: ${GITHUB_USER_ID})"
echo "github_user_id=${GITHUB_USER_ID}" >> "${GITHUB_OUTPUT}"
echo "github_username=${GITHUB_ACTOR}" >> "${GITHUB_OUTPUT}"
echo "Using PR URL: ${INPUTS_PR_URL}"
# Convert /pull/ to /issues/ for create-task-action compatibility
ISSUE_URL="${INPUTS_PR_URL/\/pull\//\/issues\/}"
echo "pr_url=${ISSUE_URL}" >> "${GITHUB_OUTPUT}"
# Extract PR number from URL for later use
PR_NUMBER=$(echo "${INPUTS_PR_URL}" | grep -oP '(?<=pull/)\d+')
echo "pr_number=${PR_NUMBER}" >> "${GITHUB_OUTPUT}"
elif [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then
GITHUB_USER_ID=${GITHUB_EVENT_SENDER_ID}
echo "Using label adder: ${GITHUB_EVENT_SENDER_LOGIN} (ID: ${GITHUB_USER_ID})"
echo "github_user_id=${GITHUB_USER_ID}" >> "${GITHUB_OUTPUT}"
echo "github_username=${GITHUB_EVENT_SENDER_LOGIN}" >> "${GITHUB_OUTPUT}"
echo "Using PR URL: ${GITHUB_EVENT_PR_HTML_URL}"
# Convert /pull/ to /issues/ for create-task-action compatibility
ISSUE_URL="${GITHUB_EVENT_PR_HTML_URL/\/pull\//\/issues\/}"
echo "pr_url=${ISSUE_URL}" >> "${GITHUB_OUTPUT}"
echo "pr_number=${GITHUB_EVENT_PR_NUMBER}" >> "${GITHUB_OUTPUT}"
else
echo "::error::Unsupported event type: ${GITHUB_EVENT_NAME}"
exit 1
fi
- name: Extract changed files and build prompt
id: extract-context
env:
PR_URL: ${{ steps.determine-context.outputs.pr_url }}
PR_NUMBER: ${{ steps.determine-context.outputs.pr_number }}
GH_TOKEN: ${{ github.token }}
run: |
echo "Analyzing PR #${PR_NUMBER}"
# Build task prompt - using unquoted heredoc so variables expand
TASK_PROMPT=$(cat <<EOF
Review PR #${PR_NUMBER} and determine if documentation needs updating or creating.
PR URL: ${PR_URL}
WORKFLOW:
1. Setup (repo is pre-cloned at ~/coder)
cd ~/coder
git fetch origin pull/${PR_NUMBER}/head:pr-${PR_NUMBER}
git checkout pr-${PR_NUMBER}
2. Get PR info
Use GitHub MCP tools to get PR title, body, and diff
Or use: git diff main...pr-${PR_NUMBER}
3. Understand Changes
Read the diff and identify what changed
Ask: Is this user-facing? Does it change behavior? Is it a new feature?
4. Search for Related Docs
cat ~/coder/docs/manifest.json | jq '.routes[] | {title, path}' | head -50
grep -ri "relevant_term" ~/coder/docs/ --include="*.md"
5. Decide
NEEDS DOCS if: New feature, API change, CLI change, behavior change, user-visible
NO DOCS if: Internal refactor, test-only, already documented, non-user-facing, dependency updates
FIRST check: Did this PR already update docs? If yes and complete, say "No Changes Needed"
6. Comment on the PR using this format
COMMENT FORMAT:
## 📚 Documentation Check
### ✅ Updates Needed
- **[docs/path/file.md](github_link)** - Brief what needs changing
### 📝 New Docs Needed
- **docs/suggested/location.md** - What should be documented
### ✨ No Changes Needed
[Reason: Documents already updated in PR | Internal changes only | Test-only | No user-facing impact]
---
*This comment was generated by an AI Agent through [Coder Tasks](https://coder.com/docs/ai-coder/tasks)*
DOCS STRUCTURE:
Read ~/coder/docs/manifest.json for the complete documentation structure.
Common areas include: reference/, admin/, user-guides/, ai-coder/, install/, tutorials/
But check manifest.json - it has everything.
EOF
)
# Output the prompt
{
echo "task_prompt<<EOFOUTPUT"
echo "${TASK_PROMPT}"
echo "EOFOUTPUT"
} >> "${GITHUB_OUTPUT}"
- name: Checkout create-task-action
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
path: ./.github/actions/create-task-action
persist-credentials: false
ref: main
repository: coder/create-task-action
- name: Create Coder Task for Documentation Check
id: create_task
uses: ./.github/actions/create-task-action
with:
coder-url: ${{ secrets.DOC_CHECK_CODER_URL }}
coder-token: ${{ secrets.DOC_CHECK_CODER_SESSION_TOKEN }}
coder-organization: "default"
coder-template-name: coder
coder-template-preset: ${{ steps.determine-context.outputs.template_preset }}
coder-task-name-prefix: doc-check
coder-task-prompt: ${{ steps.extract-context.outputs.task_prompt }}
github-user-id: ${{ steps.determine-context.outputs.github_user_id }}
github-token: ${{ github.token }}
github-issue-url: ${{ steps.determine-context.outputs.pr_url }}
comment-on-issue: true
- name: Write outputs
env:
TASK_CREATED: ${{ steps.create_task.outputs.task-created }}
TASK_NAME: ${{ steps.create_task.outputs.task-name }}
TASK_URL: ${{ steps.create_task.outputs.task-url }}
PR_URL: ${{ steps.determine-context.outputs.pr_url }}
run: |
{
echo "## Documentation Check Task"
echo ""
echo "**PR:** ${PR_URL}"
echo "**Task created:** ${TASK_CREATED}"
echo "**Task name:** ${TASK_NAME}"
echo "**Task URL:** ${TASK_URL}"
echo ""
echo "The Coder task is analyzing the PR changes and will comment with documentation recommendations."
} >> "${GITHUB_STEP_SUMMARY}"
+1 -1
View File
@@ -43,7 +43,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
+2 -2
View File
@@ -23,14 +23,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Setup Node
uses: ./.github/actions/setup-node
- uses: tj-actions/changed-files@70069877f29101175ed2b055d210fe8b1d54d7d7 # v45.0.7
- uses: tj-actions/changed-files@abdd2f68ea150cee8f236d4a9fb4e0f2491abf1b # v45.0.7
id: changed-files
with:
files: |
+2 -2
View File
@@ -31,7 +31,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
@@ -130,7 +130,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
+1 -1
View File
@@ -53,7 +53,7 @@ jobs:
uses: coder/setup-ramdisk-action@e1100847ab2d7bcd9d14bcda8f2d1b0f07b36f1b # v0.1.0
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
+4 -4
View File
@@ -44,7 +44,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
@@ -81,7 +81,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -233,7 +233,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -337,7 +337,7 @@ jobs:
kubectl create namespace "pr${PR_NUMBER}"
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
+4 -4
View File
@@ -65,7 +65,7 @@ jobs:
steps:
# Harden Runner doesn't work on macOS.
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -169,7 +169,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -888,7 +888,7 @@ jobs:
GH_TOKEN: ${{ secrets.CDRCI_GITHUB_TOKEN }}
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -976,7 +976,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
persist-credentials: false
+2 -2
View File
@@ -25,7 +25,7 @@ jobs:
egress-policy: audit
- name: "Checkout code"
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
@@ -47,6 +47,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5
with:
sarif_file: results.sarif
+5 -5
View File
@@ -32,7 +32,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
@@ -40,7 +40,7 @@ jobs:
uses: ./.github/actions/setup-go
- name: Initialize CodeQL
uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5
with:
languages: go, javascript
@@ -50,7 +50,7 @@ jobs:
rm Makefile
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5
- name: Send Slack notification on failure
if: ${{ failure() }}
@@ -74,7 +74,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 0
persist-credentials: false
@@ -154,7 +154,7 @@ jobs:
severity: "CRITICAL,HIGH"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
uses: github/codeql-action/upload-sarif@fe4161a26a8629af62121b670040955b330f9af2 # v3.29.5
with:
sarif_file: trivy-results.sarif
category: "Trivy"
+1 -1
View File
@@ -101,7 +101,7 @@ jobs:
egress-policy: audit
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Run delete-old-branches-action
+1 -1
View File
@@ -153,7 +153,7 @@ jobs:
} >> "${GITHUB_OUTPUT}"
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
fetch-depth: 1
path: ./.github/actions/create-task-action
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
egress-policy: audit
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
+3
View File
@@ -90,6 +90,9 @@ __debug_bin*
**/.claude/settings.local.json
# Local agent configuration
AGENTS.local.md
/.env
# Ignore plans written by AI agents.
+3
View File
@@ -0,0 +1,3 @@
{
"ignores": ["PLAN.md"],
}
+57
View File
@@ -140,13 +140,70 @@ seems like it should use `time.Sleep`, read through https://github.com/coder/qua
- Follow [Uber Go Style Guide](https://github.com/uber-go/guide/blob/master/style.md)
- Commit format: `type(scope): message`
### Writing Comments
Code comments should be clear, well-formatted, and add meaningful context.
**Proper sentence structure**: Comments are sentences and should end with
periods or other appropriate punctuation. This improves readability and
maintains professional code standards.
**Explain why, not what**: Good comments explain the reasoning behind code
rather than describing what the code does. The code itself should be
self-documenting through clear naming and structure. Focus your comments on
non-obvious decisions, edge cases, or business logic that isn't immediately
apparent from reading the implementation.
**Line length and wrapping**: Keep comment lines to 80 characters wide
(including the comment prefix like `//` or `#`). When a comment spans multiple
lines, wrap it naturally at word boundaries rather than writing one sentence
per line. This creates more readable, paragraph-like blocks of documentation.
```go
// Good: Explains the rationale with proper sentence structure.
// We need a custom timeout here because workspace builds can take several
// minutes on slow networks, and the default 30s timeout causes false
// failures during initial template imports.
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
// Bad: Describes what the code does without punctuation or wrapping
// Set a custom timeout
// Workspace builds can take a long time
// Default timeout is too short
ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
```
### Avoid Unnecessary Changes
When fixing a bug or adding a feature, don't modify code unrelated to your
task. Unnecessary changes make PRs harder to review and can introduce
regressions.
**Don't reword existing comments or code** unless the change is directly
motivated by your task. Rewording comments to be shorter or "cleaner" wastes
reviewer time and clutters the diff.
**Don't delete existing comments** that explain non-obvious behavior. These
comments preserve important context about why code works a certain way.
**When adding tests for new behavior**, add new test cases instead of modifying
existing ones. This preserves coverage for the original behavior and makes it
clear what the new test covers.
## Detailed Development Guides
@.claude/docs/ARCHITECTURE.md
@.claude/docs/OAUTH2.md
@.claude/docs/TESTING.md
@.claude/docs/TROUBLESHOOTING.md
@.claude/docs/DATABASE.md
## Local Configuration
These files may be gitignored, read manually if not auto-loaded.
@AGENTS.local.md
## Common Pitfalls
1. **Audit table errors** → Update `enterprise/audit/table.go`
+2
View File
@@ -27,3 +27,5 @@ coderd/schedule/autostop.go @deansheather @DanielleMaywood
# well as guidance from revenue.
coderd/usage/ @deansheather @spikecurtis
enterprise/coderd/usage/ @deansheather @spikecurtis
.github/ @jdomeracki-coder
+98 -51
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"hash/fnv"
"io"
"maps"
"net"
"net/http"
"net/netip"
@@ -40,6 +41,7 @@ import (
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/agent/agentexec"
"github.com/coder/coder/v2/agent/agentscripts"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/agentssh"
"github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/agent/proto/resourcesmonitor"
@@ -70,16 +72,21 @@ const (
)
type Options struct {
Filesystem afero.Fs
LogDir string
TempDir string
ScriptDataDir string
Client Client
ReconnectingPTYTimeout time.Duration
EnvironmentVariables map[string]string
Logger slog.Logger
IgnorePorts map[int]string
PortCacheDuration time.Duration
Filesystem afero.Fs
LogDir string
TempDir string
ScriptDataDir string
Client Client
ReconnectingPTYTimeout time.Duration
EnvironmentVariables map[string]string
Logger slog.Logger
// IgnorePorts tells the api handler which ports to ignore when
// listing all listening ports. This is helpful to hide ports that
// are used by the agent, that the user does not care about.
IgnorePorts map[int]string
// ListeningPortsGetter is used to get the list of listening ports. Only
// tests should set this. If unset, a default that queries the OS will be used.
ListeningPortsGetter ListeningPortsGetter
SSHMaxTimeout time.Duration
TailnetListenPort uint16
Subsystems []codersdk.AgentSubsystem
@@ -91,6 +98,8 @@ type Options struct {
Devcontainers bool
DevcontainerAPIOptions []agentcontainers.Option // Enable Devcontainers for these to be effective.
Clock quartz.Clock
SocketServerEnabled bool
SocketPath string // Path for the agent socket server socket
}
type Client interface {
@@ -137,9 +146,7 @@ func New(options Options) Agent {
if options.ServiceBannerRefreshInterval == 0 {
options.ServiceBannerRefreshInterval = 2 * time.Minute
}
if options.PortCacheDuration == 0 {
options.PortCacheDuration = 1 * time.Second
}
if options.Clock == nil {
options.Clock = quartz.NewReal()
}
@@ -153,30 +160,38 @@ func New(options Options) Agent {
options.Execer = agentexec.DefaultExecer
}
if options.ListeningPortsGetter == nil {
options.ListeningPortsGetter = &osListeningPortsGetter{
cacheDuration: 1 * time.Second,
}
}
hardCtx, hardCancel := context.WithCancel(context.Background())
gracefulCtx, gracefulCancel := context.WithCancel(hardCtx)
a := &agent{
clock: options.Clock,
tailnetListenPort: options.TailnetListenPort,
reconnectingPTYTimeout: options.ReconnectingPTYTimeout,
logger: options.Logger,
gracefulCtx: gracefulCtx,
gracefulCancel: gracefulCancel,
hardCtx: hardCtx,
hardCancel: hardCancel,
coordDisconnected: make(chan struct{}),
environmentVariables: options.EnvironmentVariables,
client: options.Client,
filesystem: options.Filesystem,
logDir: options.LogDir,
tempDir: options.TempDir,
scriptDataDir: options.ScriptDataDir,
lifecycleUpdate: make(chan struct{}, 1),
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
lifecycleStates: []agentsdk.PostLifecycleRequest{{State: codersdk.WorkspaceAgentLifecycleCreated}},
reportConnectionsUpdate: make(chan struct{}, 1),
ignorePorts: options.IgnorePorts,
portCacheDuration: options.PortCacheDuration,
clock: options.Clock,
tailnetListenPort: options.TailnetListenPort,
reconnectingPTYTimeout: options.ReconnectingPTYTimeout,
logger: options.Logger,
gracefulCtx: gracefulCtx,
gracefulCancel: gracefulCancel,
hardCtx: hardCtx,
hardCancel: hardCancel,
coordDisconnected: make(chan struct{}),
environmentVariables: options.EnvironmentVariables,
client: options.Client,
filesystem: options.Filesystem,
logDir: options.LogDir,
tempDir: options.TempDir,
scriptDataDir: options.ScriptDataDir,
lifecycleUpdate: make(chan struct{}, 1),
lifecycleReported: make(chan codersdk.WorkspaceAgentLifecycle, 1),
lifecycleStates: []agentsdk.PostLifecycleRequest{{State: codersdk.WorkspaceAgentLifecycleCreated}},
reportConnectionsUpdate: make(chan struct{}, 1),
listeningPortsHandler: listeningPortsHandler{
getter: options.ListeningPortsGetter,
ignorePorts: maps.Clone(options.IgnorePorts),
},
reportMetadataInterval: options.ReportMetadataInterval,
announcementBannersRefreshInterval: options.ServiceBannerRefreshInterval,
sshMaxTimeout: options.SSHMaxTimeout,
@@ -190,6 +205,8 @@ func New(options Options) Agent {
devcontainers: options.Devcontainers,
containerAPIOptions: options.DevcontainerAPIOptions,
socketPath: options.SocketPath,
socketServerEnabled: options.SocketServerEnabled,
}
// Initially, we have a closed channel, reflecting the fact that we are not initially connected.
// Each time we connect we replace the channel (while holding the closeMutex) with a new one
@@ -202,20 +219,16 @@ func New(options Options) Agent {
}
type agent struct {
clock quartz.Clock
logger slog.Logger
client Client
tailnetListenPort uint16
filesystem afero.Fs
logDir string
tempDir string
scriptDataDir string
// ignorePorts tells the api handler which ports to ignore when
// listing all listening ports. This is helpful to hide ports that
// are used by the agent, that the user does not care about.
ignorePorts map[int]string
portCacheDuration time.Duration
subsystems []codersdk.AgentSubsystem
clock quartz.Clock
logger slog.Logger
client Client
tailnetListenPort uint16
filesystem afero.Fs
logDir string
tempDir string
scriptDataDir string
listeningPortsHandler listeningPortsHandler
subsystems []codersdk.AgentSubsystem
reconnectingPTYTimeout time.Duration
reconnectingPTYServer *reconnectingpty.Server
@@ -271,6 +284,10 @@ type agent struct {
devcontainers bool
containerAPIOptions []agentcontainers.Option
containerAPI *agentcontainers.API
socketServerEnabled bool
socketPath string
socketServer *agentsocket.Server
}
func (a *agent) TailnetConn() *tailnet.Conn {
@@ -350,9 +367,32 @@ func (a *agent) init() {
s.ExperimentalContainers = a.devcontainers
},
)
a.initSocketServer()
go a.runLoop()
}
// initSocketServer initializes server that allows direct communication with a workspace agent using IPC.
func (a *agent) initSocketServer() {
if !a.socketServerEnabled {
a.logger.Info(a.hardCtx, "socket server is disabled")
return
}
server, err := agentsocket.NewServer(
a.logger.Named("socket"),
agentsocket.WithPath(a.socketPath),
)
if err != nil {
a.logger.Warn(a.hardCtx, "failed to create socket server", slog.Error(err), slog.F("path", a.socketPath))
return
}
a.socketServer = server
a.logger.Debug(a.hardCtx, "socket server started", slog.F("path", a.socketPath))
}
// runLoop attempts to start the agent in a retry loop.
// Coder may be offline temporarily, a connection issue
// may be happening, but regardless after the intermittent
@@ -1087,7 +1127,7 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context,
if err != nil {
return xerrors.Errorf("fetch metadata: %w", err)
}
a.logger.Info(ctx, "fetched manifest", slog.F("manifest", mp))
a.logger.Info(ctx, "fetched manifest")
manifest, err := agentsdk.ManifestFromProto(mp)
if err != nil {
a.logger.Critical(ctx, "failed to convert manifest", slog.F("manifest", mp), slog.Error(err))
@@ -1536,8 +1576,8 @@ func (a *agent) createTailnet(
break
}
clog := a.logger.Named("speedtest").With(
slog.F("remote", conn.RemoteAddr().String()),
slog.F("local", conn.LocalAddr().String()))
slog.F("remote", conn.RemoteAddr()),
slog.F("local", conn.LocalAddr()))
clog.Info(ctx, "accepted conn")
wg.Add(1)
closed := make(chan struct{})
@@ -1920,6 +1960,7 @@ func (a *agent) Close() error {
lifecycleState = codersdk.WorkspaceAgentLifecycleShutdownError
}
}
a.setLifecycle(lifecycleState)
err = a.scriptRunner.Close()
@@ -1927,6 +1968,12 @@ func (a *agent) Close() error {
a.logger.Error(a.hardCtx, "script runner close", slog.Error(err))
}
if a.socketServer != nil {
if err := a.socketServer.Close(); err != nil {
a.logger.Error(a.hardCtx, "socket server close", slog.Error(err))
}
}
if err := a.containerAPI.Close(); err != nil {
a.logger.Error(a.hardCtx, "container API close", slog.Error(err))
}
+45
View File
@@ -0,0 +1,45 @@
package agent
import (
"testing"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/slogtest"
"github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/testutil"
)
// TestReportConnectionEmpty tests that reportConnection() doesn't choke if given an empty IP string, which is what we
// send if we cannot get the remote address.
func TestReportConnectionEmpty(t *testing.T) {
t.Parallel()
connID := uuid.UUID{1}
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
ctx := testutil.Context(t, testutil.WaitShort)
uut := &agent{
hardCtx: ctx,
logger: logger,
}
disconnected := uut.reportConnection(connID, proto.Connection_TYPE_UNSPECIFIED, "")
require.Len(t, uut.reportConnections, 1)
req0 := uut.reportConnections[0]
require.Equal(t, proto.Connection_TYPE_UNSPECIFIED, req0.GetConnection().GetType())
require.Equal(t, "", req0.GetConnection().Ip)
require.Equal(t, connID[:], req0.GetConnection().GetId())
require.Equal(t, proto.Connection_CONNECT, req0.GetConnection().GetAction())
disconnected(0, "because")
require.Len(t, uut.reportConnections, 2)
req1 := uut.reportConnections[1]
require.Equal(t, proto.Connection_TYPE_UNSPECIFIED, req1.GetConnection().GetType())
require.Equal(t, "", req1.GetConnection().Ip)
require.Equal(t, connID[:], req1.GetConnection().GetId())
require.Equal(t, proto.Connection_DISCONNECT, req1.GetConnection().GetAction())
require.Equal(t, "because", req1.GetConnection().GetReason())
}
+44 -19
View File
@@ -1039,6 +1039,10 @@ func (api *API) processUpdatedContainersLocked(ctx context.Context, updated code
logger.Error(ctx, "inject subagent into container failed", slog.Error(err))
dc.Error = err.Error()
} else {
// TODO(mafredri): Preserve the error from devcontainer
// up if it was a lifecycle script error. Currently
// this results in a brief flicker for the user if
// injection is fast, as the error is shown then erased.
dc.Error = ""
}
}
@@ -1347,27 +1351,41 @@ func (api *API) CreateDevcontainer(workspaceFolder, configPath string, opts ...D
upOptions := []DevcontainerCLIUpOptions{WithUpOutput(infoW, errW)}
upOptions = append(upOptions, opts...)
_, err := api.dccli.Up(ctx, dc.WorkspaceFolder, configPath, upOptions...)
if err != nil {
containerID, upErr := api.dccli.Up(ctx, dc.WorkspaceFolder, configPath, upOptions...)
if upErr != nil {
// No need to log if the API is closing (context canceled), as this
// is expected behavior when the API is shutting down.
if !errors.Is(err, context.Canceled) {
logger.Error(ctx, "devcontainer creation failed", slog.Error(err))
if !errors.Is(upErr, context.Canceled) {
logger.Error(ctx, "devcontainer creation failed", slog.Error(upErr))
}
api.mu.Lock()
dc = api.knownDevcontainers[dc.WorkspaceFolder]
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusError
dc.Error = err.Error()
api.knownDevcontainers[dc.WorkspaceFolder] = dc
api.recreateErrorTimes[dc.WorkspaceFolder] = api.clock.Now("agentcontainers", "recreate", "errorTimes")
api.mu.Unlock()
// If we don't have a container ID, the error is fatal, so we
// should mark the devcontainer as errored and return.
if containerID == "" {
api.mu.Lock()
dc = api.knownDevcontainers[dc.WorkspaceFolder]
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusError
dc.Error = upErr.Error()
api.knownDevcontainers[dc.WorkspaceFolder] = dc
api.recreateErrorTimes[dc.WorkspaceFolder] = api.clock.Now("agentcontainers", "recreate", "errorTimes")
api.broadcastUpdatesLocked()
api.mu.Unlock()
return xerrors.Errorf("start devcontainer: %w", err)
return xerrors.Errorf("start devcontainer: %w", upErr)
}
// If we have a container ID, it means the container was created
// but a lifecycle script (e.g. postCreateCommand) failed. In this
// case, we still want to refresh containers to pick up the new
// container, inject the agent, and allow the user to debug the
// issue. We store the error to surface it to the user.
logger.Warn(ctx, "devcontainer created with errors (e.g. lifecycle script failure), container is available",
slog.F("container_id", containerID),
)
} else {
logger.Info(ctx, "devcontainer created successfully")
}
logger.Info(ctx, "devcontainer created successfully")
api.mu.Lock()
dc = api.knownDevcontainers[dc.WorkspaceFolder]
// Update the devcontainer status to Running or Stopped based on the
@@ -1376,13 +1394,18 @@ func (api *API) CreateDevcontainer(workspaceFolder, configPath string, opts ...D
// to minimize the time between API consistency, we guess the status
// based on the container state.
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusStopped
if dc.Container != nil {
if dc.Container.Running {
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusRunning
}
if dc.Container != nil && dc.Container.Running {
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusRunning
}
dc.Dirty = false
dc.Error = ""
if upErr != nil {
// If there was a lifecycle script error but we have a container ID,
// the container is running so we should set the status to Running.
dc.Status = codersdk.WorkspaceAgentDevcontainerStatusRunning
dc.Error = upErr.Error()
} else {
dc.Error = ""
}
api.recreateSuccessTimes[dc.WorkspaceFolder] = api.clock.Now("agentcontainers", "recreate", "successTimes")
api.knownDevcontainers[dc.WorkspaceFolder] = dc
api.broadcastUpdatesLocked()
@@ -1434,6 +1457,8 @@ func (api *API) markDevcontainerDirty(configPath string, modifiedAt time.Time) {
api.knownDevcontainers[dc.WorkspaceFolder] = dc
}
api.broadcastUpdatesLocked()
}
// cleanupSubAgents removes subagents that are no longer managed by
+196
View File
@@ -234,6 +234,8 @@ func (w *fakeWatcher) sendEventWaitNextCalled(ctx context.Context, event fsnotif
// fakeSubAgentClient implements SubAgentClient for testing purposes.
type fakeSubAgentClient struct {
logger slog.Logger
mu sync.Mutex // Protects following.
agents map[uuid.UUID]agentcontainers.SubAgent
listErrC chan error // If set, send to return error, close to return nil.
@@ -254,6 +256,8 @@ func (m *fakeSubAgentClient) List(ctx context.Context) ([]agentcontainers.SubAge
}
}
}
m.mu.Lock()
defer m.mu.Unlock()
var agents []agentcontainers.SubAgent
for _, agent := range m.agents {
agents = append(agents, agent)
@@ -283,6 +287,9 @@ func (m *fakeSubAgentClient) Create(ctx context.Context, agent agentcontainers.S
return agentcontainers.SubAgent{}, xerrors.New("operating system must be set")
}
m.mu.Lock()
defer m.mu.Unlock()
for _, a := range m.agents {
if a.Name == agent.Name {
return agentcontainers.SubAgent{}, &pq.Error{
@@ -314,6 +321,8 @@ func (m *fakeSubAgentClient) Delete(ctx context.Context, id uuid.UUID) error {
}
}
}
m.mu.Lock()
defer m.mu.Unlock()
if m.agents == nil {
m.agents = make(map[uuid.UUID]agentcontainers.SubAgent)
}
@@ -1632,6 +1641,77 @@ func TestAPI(t *testing.T) {
require.NotNil(t, response.Devcontainers[0].Container, "container should not be nil")
})
// Verify that modifying a config file broadcasts the dirty status
// over websocket immediately.
t.Run("FileWatcherDirtyBroadcast", func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
configPath := "/workspace/project/.devcontainer/devcontainer.json"
fWatcher := newFakeWatcher(t)
fLister := &fakeContainerCLI{
containers: codersdk.WorkspaceAgentListContainersResponse{
Containers: []codersdk.WorkspaceAgentContainer{
{
ID: "container-id",
FriendlyName: "container-name",
Running: true,
Labels: map[string]string{
agentcontainers.DevcontainerLocalFolderLabel: "/workspace/project",
agentcontainers.DevcontainerConfigFileLabel: configPath,
},
},
},
},
}
mClock := quartz.NewMock(t)
tickerTrap := mClock.Trap().TickerFunc("updaterLoop")
api := agentcontainers.NewAPI(
slogtest.Make(t, nil).Leveled(slog.LevelDebug),
agentcontainers.WithContainerCLI(fLister),
agentcontainers.WithWatcher(fWatcher),
agentcontainers.WithClock(mClock),
)
api.Start()
defer api.Close()
srv := httptest.NewServer(api.Routes())
defer srv.Close()
tickerTrap.MustWait(ctx).MustRelease(ctx)
tickerTrap.Close()
wsConn, resp, err := websocket.Dial(ctx, "ws"+strings.TrimPrefix(srv.URL, "http")+"/watch", nil)
require.NoError(t, err)
if resp != nil && resp.Body != nil {
defer resp.Body.Close()
}
defer wsConn.Close(websocket.StatusNormalClosure, "")
// Read and discard initial state.
_, _, err = wsConn.Read(ctx)
require.NoError(t, err)
fWatcher.waitNext(ctx)
fWatcher.sendEventWaitNextCalled(ctx, fsnotify.Event{
Name: configPath,
Op: fsnotify.Write,
})
// Verify dirty status is broadcast without advancing the clock.
_, msg, err := wsConn.Read(ctx)
require.NoError(t, err)
var response codersdk.WorkspaceAgentListContainersResponse
err = json.Unmarshal(msg, &response)
require.NoError(t, err)
require.Len(t, response.Devcontainers, 1)
assert.True(t, response.Devcontainers[0].Dirty,
"devcontainer should be marked as dirty after config file modification")
})
t.Run("SubAgentLifecycle", func(t *testing.T) {
t.Parallel()
@@ -2070,6 +2150,122 @@ func TestAPI(t *testing.T) {
require.Equal(t, "", response.Devcontainers[0].Error)
})
// This test verifies that when devcontainer up fails due to a
// lifecycle script error (such as postCreateCommand failing) but the
// container was successfully created, we still proceed with the
// devcontainer. The container should be available for use and the
// agent should be injected.
t.Run("DuringUpWithContainerID", func(t *testing.T) {
t.Parallel()
var (
ctx = testutil.Context(t, testutil.WaitMedium)
logger = slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).Leveled(slog.LevelDebug)
mClock = quartz.NewMock(t)
testContainer = codersdk.WorkspaceAgentContainer{
ID: "test-container-id",
FriendlyName: "test-container",
Image: "test-image",
Running: true,
CreatedAt: time.Now(),
Labels: map[string]string{
agentcontainers.DevcontainerLocalFolderLabel: "/workspaces/project",
agentcontainers.DevcontainerConfigFileLabel: "/workspaces/project/.devcontainer/devcontainer.json",
},
}
fCCLI = &fakeContainerCLI{
containers: codersdk.WorkspaceAgentListContainersResponse{
Containers: []codersdk.WorkspaceAgentContainer{testContainer},
},
arch: "amd64",
}
fDCCLI = &fakeDevcontainerCLI{
upID: testContainer.ID,
upErrC: make(chan func() error, 1),
}
fSAC = &fakeSubAgentClient{
logger: logger.Named("fakeSubAgentClient"),
}
testDevcontainer = codersdk.WorkspaceAgentDevcontainer{
ID: uuid.New(),
Name: "test-devcontainer",
WorkspaceFolder: "/workspaces/project",
ConfigPath: "/workspaces/project/.devcontainer/devcontainer.json",
Status: codersdk.WorkspaceAgentDevcontainerStatusStopped,
}
)
mClock.Set(time.Now()).MustWait(ctx)
tickerTrap := mClock.Trap().TickerFunc("updaterLoop")
nowRecreateSuccessTrap := mClock.Trap().Now("recreate", "successTimes")
api := agentcontainers.NewAPI(logger,
agentcontainers.WithClock(mClock),
agentcontainers.WithContainerCLI(fCCLI),
agentcontainers.WithDevcontainerCLI(fDCCLI),
agentcontainers.WithDevcontainers(
[]codersdk.WorkspaceAgentDevcontainer{testDevcontainer},
[]codersdk.WorkspaceAgentScript{{ID: testDevcontainer.ID, LogSourceID: uuid.New()}},
),
agentcontainers.WithSubAgentClient(fSAC),
agentcontainers.WithSubAgentURL("test-subagent-url"),
agentcontainers.WithWatcher(watcher.NewNoop()),
)
api.Start()
defer func() {
close(fDCCLI.upErrC)
api.Close()
}()
r := chi.NewRouter()
r.Mount("/", api.Routes())
tickerTrap.MustWait(ctx).MustRelease(ctx)
tickerTrap.Close()
// Send a recreate request to trigger devcontainer up.
req := httptest.NewRequest(http.MethodPost, "/devcontainers/"+testDevcontainer.ID.String()+"/recreate", nil)
rec := httptest.NewRecorder()
r.ServeHTTP(rec, req)
require.Equal(t, http.StatusAccepted, rec.Code)
// Simulate a lifecycle script failure. The devcontainer CLI
// will return an error but also provide a container ID since
// the container was created before the script failed.
simulatedError := xerrors.New("postCreateCommand failed with exit code 1")
testutil.RequireSend(ctx, t, fDCCLI.upErrC, func() error { return simulatedError })
// Wait for the recreate operation to complete. We expect it to
// record a success time because the container was created.
nowRecreateSuccessTrap.MustWait(ctx).MustRelease(ctx)
nowRecreateSuccessTrap.Close()
// Advance the clock to run the devcontainer state update routine.
_, aw := mClock.AdvanceNext()
aw.MustWait(ctx)
req = httptest.NewRequest(http.MethodGet, "/", nil)
rec = httptest.NewRecorder()
r.ServeHTTP(rec, req)
require.Equal(t, http.StatusOK, rec.Code)
var response codersdk.WorkspaceAgentListContainersResponse
err := json.NewDecoder(rec.Body).Decode(&response)
require.NoError(t, err)
// Verify that the devcontainer is running and has the container
// associated with it despite the lifecycle script error. The
// error may be cleared during refresh if agent injection
// succeeds, but the important thing is that the container is
// available for use.
require.Len(t, response.Devcontainers, 1)
assert.Equal(t, codersdk.WorkspaceAgentDevcontainerStatusRunning, response.Devcontainers[0].Status)
require.NotNil(t, response.Devcontainers[0].Container)
assert.Equal(t, testContainer.ID, response.Devcontainers[0].Container.ID)
})
t.Run("DuringInjection", func(t *testing.T) {
t.Parallel()
+16 -15
View File
@@ -263,11 +263,14 @@ func (d *devcontainerCLI) Up(ctx context.Context, workspaceFolder, configPath st
}
if err := cmd.Run(); err != nil {
_, err2 := parseDevcontainerCLILastLine[devcontainerCLIResult](ctx, logger, stdoutBuf.Bytes())
result, err2 := parseDevcontainerCLILastLine[devcontainerCLIResult](ctx, logger, stdoutBuf.Bytes())
if err2 != nil {
err = errors.Join(err, err2)
}
return "", err
// Return the container ID if available, even if there was an error.
// This can happen if the container was created successfully but a
// lifecycle script (e.g. postCreateCommand) failed.
return result.ContainerID, err
}
result, err := parseDevcontainerCLILastLine[devcontainerCLIResult](ctx, logger, stdoutBuf.Bytes())
@@ -275,6 +278,13 @@ func (d *devcontainerCLI) Up(ctx context.Context, workspaceFolder, configPath st
return "", err
}
// Check if the result indicates an error (e.g. lifecycle script failure)
// but still has a container ID, allowing the caller to potentially
// continue with the container that was created.
if err := result.Err(); err != nil {
return result.ContainerID, err
}
return result.ContainerID, nil
}
@@ -394,7 +404,10 @@ func parseDevcontainerCLILastLine[T any](ctx context.Context, logger slog.Logger
type devcontainerCLIResult struct {
Outcome string `json:"outcome"` // "error", "success".
// The following fields are set if outcome is success.
// The following fields are typically set if outcome is success, but
// ContainerID may also be present when outcome is error if the
// container was created but a lifecycle script (e.g. postCreateCommand)
// failed.
ContainerID string `json:"containerId"`
RemoteUser string `json:"remoteUser"`
RemoteWorkspaceFolder string `json:"remoteWorkspaceFolder"`
@@ -404,18 +417,6 @@ type devcontainerCLIResult struct {
Description string `json:"description"`
}
func (r *devcontainerCLIResult) UnmarshalJSON(data []byte) error {
type wrapperResult devcontainerCLIResult
var wrappedResult wrapperResult
if err := json.Unmarshal(data, &wrappedResult); err != nil {
return err
}
*r = devcontainerCLIResult(wrappedResult)
return r.Err()
}
func (r devcontainerCLIResult) Err() error {
if r.Outcome == "success" {
return nil
+64 -41
View File
@@ -42,56 +42,63 @@ func TestDevcontainerCLI_ArgsAndParsing(t *testing.T) {
t.Parallel()
tests := []struct {
name string
logFile string
workspace string
config string
opts []agentcontainers.DevcontainerCLIUpOptions
wantArgs string
wantError bool
name string
logFile string
workspace string
config string
opts []agentcontainers.DevcontainerCLIUpOptions
wantArgs string
wantError bool
wantContainerID bool // If true, expect a container ID even when wantError is true.
}{
{
name: "success",
logFile: "up.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: false,
name: "success",
logFile: "up.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: false,
wantContainerID: true,
},
{
name: "success with config",
logFile: "up.log",
workspace: "/test/workspace",
config: "/test/config.json",
wantArgs: "up --log-format json --workspace-folder /test/workspace --config /test/config.json",
wantError: false,
name: "success with config",
logFile: "up.log",
workspace: "/test/workspace",
config: "/test/config.json",
wantArgs: "up --log-format json --workspace-folder /test/workspace --config /test/config.json",
wantError: false,
wantContainerID: true,
},
{
name: "already exists",
logFile: "up-already-exists.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: false,
name: "already exists",
logFile: "up-already-exists.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: false,
wantContainerID: true,
},
{
name: "docker error",
logFile: "up-error-docker.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: true,
name: "docker error",
logFile: "up-error-docker.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: true,
wantContainerID: false,
},
{
name: "bad outcome",
logFile: "up-error-bad-outcome.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: true,
name: "bad outcome",
logFile: "up-error-bad-outcome.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: true,
wantContainerID: false,
},
{
name: "does not exist",
logFile: "up-error-does-not-exist.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: true,
name: "does not exist",
logFile: "up-error-does-not-exist.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: true,
wantContainerID: false,
},
{
name: "with remove existing container",
@@ -100,8 +107,21 @@ func TestDevcontainerCLI_ArgsAndParsing(t *testing.T) {
opts: []agentcontainers.DevcontainerCLIUpOptions{
agentcontainers.WithRemoveExistingContainer(),
},
wantArgs: "up --log-format json --workspace-folder /test/workspace --remove-existing-container",
wantError: false,
wantArgs: "up --log-format json --workspace-folder /test/workspace --remove-existing-container",
wantError: false,
wantContainerID: true,
},
{
// This test verifies that when a lifecycle script like
// postCreateCommand fails, the CLI returns both an error
// and a container ID. The caller can then proceed with
// agent injection into the created container.
name: "lifecycle script failure with container",
logFile: "up-error-lifecycle-script.log",
workspace: "/test/workspace",
wantArgs: "up --log-format json --workspace-folder /test/workspace",
wantError: true,
wantContainerID: true,
},
}
@@ -122,10 +142,13 @@ func TestDevcontainerCLI_ArgsAndParsing(t *testing.T) {
containerID, err := dccli.Up(ctx, tt.workspace, tt.config, tt.opts...)
if tt.wantError {
assert.Error(t, err, "want error")
assert.Empty(t, containerID, "expected empty container ID")
} else {
assert.NoError(t, err, "want no error")
}
if tt.wantContainerID {
assert.NotEmpty(t, containerID, "expected non-empty container ID")
} else {
assert.Empty(t, containerID, "expected empty container ID")
}
})
}
File diff suppressed because one or more lines are too long
+146
View File
@@ -0,0 +1,146 @@
package agentsocket
import (
"context"
"golang.org/x/xerrors"
"storj.io/drpc"
"storj.io/drpc/drpcconn"
"github.com/coder/coder/v2/agent/agentsocket/proto"
"github.com/coder/coder/v2/agent/unit"
)
// Option represents a configuration option for NewClient.
type Option func(*options)
type options struct {
path string
}
// WithPath sets the socket path. If not provided or empty, the client will
// auto-discover the default socket path.
func WithPath(path string) Option {
return func(opts *options) {
if path == "" {
return
}
opts.path = path
}
}
// Client provides a client for communicating with the workspace agentsocket API.
type Client struct {
client proto.DRPCAgentSocketClient
conn drpc.Conn
}
// NewClient creates a new socket client and opens a connection to the socket.
// If path is not provided via WithPath or is empty, it will auto-discover the
// default socket path.
func NewClient(ctx context.Context, opts ...Option) (*Client, error) {
options := &options{}
for _, opt := range opts {
opt(options)
}
conn, err := dialSocket(ctx, options.path)
if err != nil {
return nil, xerrors.Errorf("connect to socket: %w", err)
}
drpcConn := drpcconn.New(conn)
client := proto.NewDRPCAgentSocketClient(drpcConn)
return &Client{
client: client,
conn: drpcConn,
}, nil
}
// Close closes the socket connection.
func (c *Client) Close() error {
return c.conn.Close()
}
// Ping sends a ping request to the agent.
func (c *Client) Ping(ctx context.Context) error {
_, err := c.client.Ping(ctx, &proto.PingRequest{})
return err
}
// SyncStart starts a unit in the dependency graph.
func (c *Client) SyncStart(ctx context.Context, unitName unit.ID) error {
_, err := c.client.SyncStart(ctx, &proto.SyncStartRequest{
Unit: string(unitName),
})
return err
}
// SyncWant declares a dependency between units.
func (c *Client) SyncWant(ctx context.Context, unitName, dependsOn unit.ID) error {
_, err := c.client.SyncWant(ctx, &proto.SyncWantRequest{
Unit: string(unitName),
DependsOn: string(dependsOn),
})
return err
}
// SyncComplete marks a unit as complete in the dependency graph.
func (c *Client) SyncComplete(ctx context.Context, unitName unit.ID) error {
_, err := c.client.SyncComplete(ctx, &proto.SyncCompleteRequest{
Unit: string(unitName),
})
return err
}
// SyncReady requests whether a unit is ready to be started. That is, all dependencies are satisfied.
func (c *Client) SyncReady(ctx context.Context, unitName unit.ID) (bool, error) {
resp, err := c.client.SyncReady(ctx, &proto.SyncReadyRequest{
Unit: string(unitName),
})
return resp.Ready, err
}
// SyncStatus gets the status of a unit and its dependencies.
func (c *Client) SyncStatus(ctx context.Context, unitName unit.ID) (SyncStatusResponse, error) {
resp, err := c.client.SyncStatus(ctx, &proto.SyncStatusRequest{
Unit: string(unitName),
})
if err != nil {
return SyncStatusResponse{}, err
}
var dependencies []DependencyInfo
for _, dep := range resp.Dependencies {
dependencies = append(dependencies, DependencyInfo{
DependsOn: unit.ID(dep.DependsOn),
RequiredStatus: unit.Status(dep.RequiredStatus),
CurrentStatus: unit.Status(dep.CurrentStatus),
IsSatisfied: dep.IsSatisfied,
})
}
return SyncStatusResponse{
UnitName: unitName,
Status: unit.Status(resp.Status),
IsReady: resp.IsReady,
Dependencies: dependencies,
}, nil
}
// SyncStatusResponse contains the status information for a unit.
type SyncStatusResponse struct {
UnitName unit.ID `table:"unit,default_sort" json:"unit_name"`
Status unit.Status `table:"status" json:"status"`
IsReady bool `table:"ready" json:"is_ready"`
Dependencies []DependencyInfo `table:"dependencies" json:"dependencies"`
}
// DependencyInfo contains information about a unit dependency.
type DependencyInfo struct {
DependsOn unit.ID `table:"depends on,default_sort" json:"depends_on"`
RequiredStatus unit.Status `table:"required status" json:"required_status"`
CurrentStatus unit.Status `table:"current status" json:"current_status"`
IsSatisfied bool `table:"satisfied" json:"is_satisfied"`
}
+12 -59
View File
@@ -7,8 +7,6 @@ import (
"sync"
"golang.org/x/xerrors"
"github.com/hashicorp/yamux"
"storj.io/drpc/drpcmux"
"storj.io/drpc/drpcserver"
@@ -33,11 +31,17 @@ type Server struct {
wg sync.WaitGroup
}
func NewServer(path string, logger slog.Logger) (*Server, error) {
// NewServer creates a new agent socket server.
func NewServer(logger slog.Logger, opts ...Option) (*Server, error) {
options := &options{}
for _, opt := range opts {
opt(options)
}
logger = logger.Named("agentsocket-server")
server := &Server{
logger: logger,
path: path,
path: options.path,
service: &DRPCAgentSocketService{
logger: logger,
unitManager: unit.NewManager(),
@@ -61,14 +65,6 @@ func NewServer(path string, logger slog.Logger) (*Server, error) {
},
})
if server.path == "" {
var err error
server.path, err = getDefaultSocketPath()
if err != nil {
return nil, xerrors.Errorf("get default socket path: %w", err)
}
}
listener, err := createSocket(server.path)
if err != nil {
return nil, xerrors.Errorf("create socket: %w", err)
@@ -91,6 +87,7 @@ func NewServer(path string, logger slog.Logger) (*Server, error) {
return server, nil
}
// Close stops the server and cleans up resources.
func (s *Server) Close() error {
s.mu.Lock()
@@ -134,52 +131,8 @@ func (s *Server) acceptConnections() {
return
}
for {
select {
case <-s.ctx.Done():
return
default:
}
conn, err := listener.Accept()
if err != nil {
s.logger.Warn(s.ctx, "error accepting connection", slog.Error(err))
continue
}
s.mu.Lock()
if s.listener == nil {
s.mu.Unlock()
_ = conn.Close()
return
}
s.wg.Add(1)
s.mu.Unlock()
go func() {
defer s.wg.Done()
s.handleConnection(conn)
}()
}
}
func (s *Server) handleConnection(conn net.Conn) {
defer conn.Close()
s.logger.Debug(s.ctx, "new connection accepted", slog.F("remote_addr", conn.RemoteAddr()))
config := yamux.DefaultConfig()
config.LogOutput = nil
config.Logger = slog.Stdlib(s.ctx, s.logger.Named("agentsocket-yamux"), slog.LevelInfo)
session, err := yamux.Server(conn, config)
if err != nil {
s.logger.Warn(s.ctx, "failed to create yamux session", slog.Error(err))
return
}
defer session.Close()
err = s.drpcServer.Serve(s.ctx, session)
if err != nil {
s.logger.Debug(s.ctx, "drpc server finished", slog.Error(err))
err := s.drpcServer.Serve(s.ctx, listener)
if err != nil {
s.logger.Warn(s.ctx, "error serving drpc server", slog.Error(err))
}
}
+90 -4
View File
@@ -1,14 +1,24 @@
package agentsocket_test
import (
"context"
"path/filepath"
"runtime"
"testing"
"github.com/google/uuid"
"github.com/spf13/afero"
"github.com/stretchr/testify/require"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/agenttest"
agentproto "github.com/coder/coder/v2/agent/proto"
"github.com/coder/coder/v2/codersdk/agentsdk"
"github.com/coder/coder/v2/tailnet"
"github.com/coder/coder/v2/tailnet/tailnettest"
"github.com/coder/coder/v2/testutil"
)
func TestServer(t *testing.T) {
@@ -23,7 +33,7 @@ func TestServer(t *testing.T) {
socketPath := filepath.Join(t.TempDir(), "test.sock")
logger := slog.Make().Leveled(slog.LevelDebug)
server, err := agentsocket.NewServer(socketPath, logger)
server, err := agentsocket.NewServer(logger, agentsocket.WithPath(socketPath))
require.NoError(t, err)
require.NoError(t, server.Close())
})
@@ -33,10 +43,10 @@ func TestServer(t *testing.T) {
socketPath := filepath.Join(t.TempDir(), "test.sock")
logger := slog.Make().Leveled(slog.LevelDebug)
server1, err := agentsocket.NewServer(socketPath, logger)
server1, err := agentsocket.NewServer(logger, agentsocket.WithPath(socketPath))
require.NoError(t, err)
defer server1.Close()
_, err = agentsocket.NewServer(socketPath, logger)
_, err = agentsocket.NewServer(logger, agentsocket.WithPath(socketPath))
require.ErrorContains(t, err, "create socket")
})
@@ -45,8 +55,84 @@ func TestServer(t *testing.T) {
socketPath := filepath.Join(t.TempDir(), "test.sock")
logger := slog.Make().Leveled(slog.LevelDebug)
server, err := agentsocket.NewServer(socketPath, logger)
server, err := agentsocket.NewServer(logger, agentsocket.WithPath(socketPath))
require.NoError(t, err)
require.NoError(t, server.Close())
})
}
func TestServerWindowsNotSupported(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" {
t.Skip("this test only runs on Windows")
}
t.Run("NewServer", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(t.TempDir(), "test.sock")
logger := slog.Make().Leveled(slog.LevelDebug)
_, err := agentsocket.NewServer(logger, agentsocket.WithPath(socketPath))
require.ErrorContains(t, err, "agentsocket is not supported on Windows")
})
t.Run("NewClient", func(t *testing.T) {
t.Parallel()
_, err := agentsocket.NewClient(context.Background(), agentsocket.WithPath("test.sock"))
require.ErrorContains(t, err, "agentsocket is not supported on Windows")
})
}
func TestAgentInitializesOnWindowsWithoutSocketServer(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" {
t.Skip("this test only runs on Windows")
}
ctx := testutil.Context(t, testutil.WaitShort)
logger := testutil.Logger(t).Named("agent")
derpMap, _ := tailnettest.RunDERPAndSTUN(t)
coordinator := tailnet.NewCoordinator(logger)
t.Cleanup(func() {
_ = coordinator.Close()
})
statsCh := make(chan *agentproto.Stats, 50)
agentID := uuid.New()
manifest := agentsdk.Manifest{
AgentID: agentID,
AgentName: "test-agent",
WorkspaceName: "test-workspace",
OwnerName: "test-user",
WorkspaceID: uuid.New(),
DERPMap: derpMap,
}
client := agenttest.NewClient(t, logger.Named("agenttest"), agentID, manifest, statsCh, coordinator)
t.Cleanup(client.Close)
options := agent.Options{
Client: client,
Filesystem: afero.NewMemMapFs(),
Logger: logger.Named("agent"),
ReconnectingPTYTimeout: testutil.WaitShort,
EnvironmentVariables: map[string]string{},
SocketPath: "",
}
agnt := agent.New(options)
t.Cleanup(func() {
_ = agnt.Close()
})
startup := testutil.TryReceive(ctx, t, client.GetStartup())
require.NotNil(t, startup, "agent should send startup message")
err := agnt.Close()
require.NoError(t, err, "agent should close cleanly")
}
+12 -2
View File
@@ -15,15 +15,18 @@ var _ proto.DRPCAgentSocketServer = (*DRPCAgentSocketService)(nil)
var ErrUnitManagerNotAvailable = xerrors.New("unit manager not available")
// DRPCAgentSocketService implements the DRPC agent socket service.
type DRPCAgentSocketService struct {
unitManager *unit.Manager
logger slog.Logger
}
// Ping responds to a ping request to check if the service is alive.
func (*DRPCAgentSocketService) Ping(_ context.Context, _ *proto.PingRequest) (*proto.PingResponse, error) {
return &proto.PingResponse{}, nil
}
// SyncStart starts a unit in the dependency graph.
func (s *DRPCAgentSocketService) SyncStart(_ context.Context, req *proto.SyncStartRequest) (*proto.SyncStartResponse, error) {
if s.unitManager == nil {
return nil, xerrors.Errorf("SyncStart: %w", ErrUnitManagerNotAvailable)
@@ -53,6 +56,7 @@ func (s *DRPCAgentSocketService) SyncStart(_ context.Context, req *proto.SyncSta
return &proto.SyncStartResponse{}, nil
}
// SyncWant declares a dependency between units.
func (s *DRPCAgentSocketService) SyncWant(_ context.Context, req *proto.SyncWantRequest) (*proto.SyncWantResponse, error) {
if s.unitManager == nil {
return nil, xerrors.Errorf("cannot add dependency: %w", ErrUnitManagerNotAvailable)
@@ -72,6 +76,7 @@ func (s *DRPCAgentSocketService) SyncWant(_ context.Context, req *proto.SyncWant
return &proto.SyncWantResponse{}, nil
}
// SyncComplete marks a unit as complete in the dependency graph.
func (s *DRPCAgentSocketService) SyncComplete(_ context.Context, req *proto.SyncCompleteRequest) (*proto.SyncCompleteResponse, error) {
if s.unitManager == nil {
return nil, xerrors.Errorf("cannot complete unit: %w", ErrUnitManagerNotAvailable)
@@ -86,6 +91,7 @@ func (s *DRPCAgentSocketService) SyncComplete(_ context.Context, req *proto.Sync
return &proto.SyncCompleteResponse{}, nil
}
// SyncReady checks whether a unit is ready to be started. That is, all dependencies are satisfied.
func (s *DRPCAgentSocketService) SyncReady(_ context.Context, req *proto.SyncReadyRequest) (*proto.SyncReadyResponse, error) {
if s.unitManager == nil {
return nil, xerrors.Errorf("cannot check readiness: %w", ErrUnitManagerNotAvailable)
@@ -102,6 +108,7 @@ func (s *DRPCAgentSocketService) SyncReady(_ context.Context, req *proto.SyncRea
}, nil
}
// SyncStatus gets the status of a unit and lists its dependencies.
func (s *DRPCAgentSocketService) SyncStatus(_ context.Context, req *proto.SyncStatusRequest) (*proto.SyncStatusResponse, error) {
if s.unitManager == nil {
return nil, xerrors.Errorf("cannot get status for unit %q: %w", req.Unit, ErrUnitManagerNotAvailable)
@@ -115,8 +122,11 @@ func (s *DRPCAgentSocketService) SyncStatus(_ context.Context, req *proto.SyncSt
}
dependencies, err := s.unitManager.GetAllDependencies(unitID)
if err != nil {
return nil, xerrors.Errorf("failed to get dependencies: %w", err)
switch {
case errors.Is(err, unit.ErrUnitNotFound):
dependencies = []unit.Dependency{}
case err != nil:
return nil, xerrors.Errorf("cannot get dependencies: %w", err)
}
var depInfos []*proto.DependencyInfo
+92 -173
View File
@@ -5,21 +5,18 @@ import (
"crypto/sha256"
"encoding/hex"
"fmt"
"net"
"os"
"path/filepath"
"runtime"
"testing"
"github.com/hashicorp/yamux"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/agentsocket/proto"
"github.com/coder/coder/v2/agent/unit"
"github.com/coder/coder/v2/codersdk/drpcsdk"
"github.com/coder/coder/v2/testutil"
)
// tempDirUnixSocket returns a temporary directory that can safely hold unix
@@ -47,23 +44,15 @@ func tempDirUnixSocket(t *testing.T) string {
}
// newSocketClient creates a DRPC client connected to the Unix socket at the given path.
func newSocketClient(t *testing.T, socketPath string) proto.DRPCAgentSocketClient {
func newSocketClient(ctx context.Context, t *testing.T, socketPath string) *agentsocket.Client {
t.Helper()
conn, err := net.Dial("unix", socketPath)
require.NoError(t, err)
config := yamux.DefaultConfig()
config.Logger = nil
session, err := yamux.Client(conn, config)
require.NoError(t, err)
client := proto.NewDRPCAgentSocketClient(drpcsdk.MultiplexedConn(session))
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(socketPath))
t.Cleanup(func() {
_ = session.Close()
_ = conn.Close()
_ = client.Close()
})
require.NoError(t, err)
return client
}
@@ -78,17 +67,17 @@ func TestDRPCAgentSocketService(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
_, err = client.Ping(context.Background(), &proto.PingRequest{})
err = client.Ping(ctx)
require.NoError(t, err)
})
@@ -98,147 +87,116 @@ func TestDRPCAgentSocketService(t *testing.T) {
t.Run("NewUnit", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
status, err := client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err := client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "started", status.Status)
require.Equal(t, unit.StatusStarted, status.Status)
})
t.Run("UnitAlreadyStarted", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
// First Start
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
status, err := client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err := client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "started", status.Status)
require.Equal(t, unit.StatusStarted, status.Status)
// Second Start
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.ErrorContains(t, err, unit.ErrSameStatusAlreadySet.Error())
status, err = client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err = client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "started", status.Status)
require.Equal(t, unit.StatusStarted, status.Status)
})
t.Run("UnitAlreadyCompleted", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
// First start
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
status, err := client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err := client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "started", status.Status)
require.Equal(t, unit.StatusStarted, status.Status)
// Complete the unit
_, err = client.SyncComplete(context.Background(), &proto.SyncCompleteRequest{
Unit: "test-unit",
})
err = client.SyncComplete(ctx, "test-unit")
require.NoError(t, err)
status, err = client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err = client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "completed", status.Status)
require.Equal(t, unit.StatusComplete, status.Status)
// Second start
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
status, err = client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err = client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "started", status.Status)
require.Equal(t, unit.StatusStarted, status.Status)
})
t.Run("UnitNotReady", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
_, err = client.SyncWant(context.Background(), &proto.SyncWantRequest{
Unit: "test-unit",
DependsOn: "dependency-unit",
})
err = client.SyncWant(ctx, "test-unit", "dependency-unit")
require.NoError(t, err)
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.ErrorContains(t, err, "unit not ready")
status, err := client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err := client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, string(unit.StatusPending), status.Status)
require.Equal(t, unit.StatusPending, status.Status)
require.False(t, status.IsReady)
})
})
@@ -250,107 +208,86 @@ func TestDRPCAgentSocketService(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
// If dependency units are not registered, they are registered automatically
_, err = client.SyncWant(context.Background(), &proto.SyncWantRequest{
Unit: "test-unit",
DependsOn: "dependency-unit",
})
err = client.SyncWant(ctx, "test-unit", "dependency-unit")
require.NoError(t, err)
status, err := client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err := client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Len(t, status.Dependencies, 1)
require.Equal(t, "dependency-unit", status.Dependencies[0].DependsOn)
require.Equal(t, "completed", status.Dependencies[0].RequiredStatus)
require.Equal(t, unit.ID("dependency-unit"), status.Dependencies[0].DependsOn)
require.Equal(t, unit.StatusComplete, status.Dependencies[0].RequiredStatus)
})
t.Run("DependencyAlreadyRegistered", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
// Start the dependency unit
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "dependency-unit",
})
err = client.SyncStart(ctx, "dependency-unit")
require.NoError(t, err)
status, err := client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "dependency-unit",
})
status, err := client.SyncStatus(ctx, "dependency-unit")
require.NoError(t, err)
require.Equal(t, "started", status.Status)
require.Equal(t, unit.StatusStarted, status.Status)
// Add the dependency after the dependency unit has already started
_, err = client.SyncWant(context.Background(), &proto.SyncWantRequest{
Unit: "test-unit",
DependsOn: "dependency-unit",
})
err = client.SyncWant(ctx, "test-unit", "dependency-unit")
// Dependencies can be added even if the dependency unit has already started
require.NoError(t, err)
// The dependency is now reflected in the test unit's status
status, err = client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err = client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "dependency-unit", status.Dependencies[0].DependsOn)
require.Equal(t, "completed", status.Dependencies[0].RequiredStatus)
require.Equal(t, unit.ID("dependency-unit"), status.Dependencies[0].DependsOn)
require.Equal(t, unit.StatusComplete, status.Dependencies[0].RequiredStatus)
})
t.Run("DependencyAddedAfterDependentStarted", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
// Start the dependent unit
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
status, err := client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err := client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "started", status.Status)
require.Equal(t, unit.StatusStarted, status.Status)
// Add the dependency after the dependency unit has already started
_, err = client.SyncWant(context.Background(), &proto.SyncWantRequest{
Unit: "test-unit",
DependsOn: "dependency-unit",
})
err = client.SyncWant(ctx, "test-unit", "dependency-unit")
// Dependencies can be added even if the dependent unit has already started.
// The dependency applies the next time a unit is started. The current status is not updated.
@@ -359,12 +296,10 @@ func TestDRPCAgentSocketService(t *testing.T) {
require.NoError(t, err)
// The dependency is now reflected in the test unit's status
status, err = client.SyncStatus(context.Background(), &proto.SyncStatusRequest{
Unit: "test-unit",
})
status, err = client.SyncStatus(ctx, "test-unit")
require.NoError(t, err)
require.Equal(t, "dependency-unit", status.Dependencies[0].DependsOn)
require.Equal(t, "completed", status.Dependencies[0].RequiredStatus)
require.Equal(t, unit.ID("dependency-unit"), status.Dependencies[0].DependsOn)
require.Equal(t, unit.StatusComplete, status.Dependencies[0].RequiredStatus)
})
})
@@ -375,96 +310,80 @@ func TestDRPCAgentSocketService(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
response, err := client.SyncReady(context.Background(), &proto.SyncReadyRequest{
Unit: "unregistered-unit",
})
ready, err := client.SyncReady(ctx, "unregistered-unit")
require.NoError(t, err)
require.False(t, response.Ready)
require.True(t, ready)
})
t.Run("UnitNotReady", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
// Register a unit with an unsatisfied dependency
_, err = client.SyncWant(context.Background(), &proto.SyncWantRequest{
Unit: "test-unit",
DependsOn: "dependency-unit",
})
err = client.SyncWant(ctx, "test-unit", "dependency-unit")
require.NoError(t, err)
// Check readiness - should be false because dependency is not satisfied
response, err := client.SyncReady(context.Background(), &proto.SyncReadyRequest{
Unit: "test-unit",
})
ready, err := client.SyncReady(ctx, "test-unit")
require.NoError(t, err)
require.False(t, response.Ready)
require.False(t, ready)
})
t.Run("UnitReady", func(t *testing.T) {
t.Parallel()
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
ctx := testutil.Context(t, testutil.WaitShort)
server, err := agentsocket.NewServer(
socketPath,
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err)
defer server.Close()
client := newSocketClient(t, socketPath)
client := newSocketClient(ctx, t, socketPath)
// Register a unit with no dependencies - should be ready immediately
_, err = client.SyncStart(context.Background(), &proto.SyncStartRequest{
Unit: "test-unit",
})
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
// Check readiness - should be true
_, err = client.SyncReady(context.Background(), &proto.SyncReadyRequest{
Unit: "test-unit",
})
ready, err := client.SyncReady(ctx, "test-unit")
require.NoError(t, err)
require.True(t, ready)
// Also test a unit with satisfied dependencies
_, err = client.SyncWant(context.Background(), &proto.SyncWantRequest{
Unit: "dependent-unit",
DependsOn: "test-unit",
})
err = client.SyncWant(ctx, "dependent-unit", "test-unit")
require.NoError(t, err)
// Complete the dependency
_, err = client.SyncComplete(context.Background(), &proto.SyncCompleteRequest{
Unit: "test-unit",
})
err = client.SyncComplete(ctx, "test-unit")
require.NoError(t, err)
// Now dependent-unit should be ready
_, err = client.SyncReady(context.Background(), &proto.SyncReadyRequest{
Unit: "dependent-unit",
})
ready, err = client.SyncReady(ctx, "dependent-unit")
require.NoError(t, err)
require.True(t, ready)
})
})
}
+17 -27
View File
@@ -3,8 +3,7 @@
package agentsocket
import (
"crypto/rand"
"encoding/hex"
"context"
"net"
"os"
"path/filepath"
@@ -13,8 +12,13 @@ import (
"golang.org/x/xerrors"
)
// createSocket creates a Unix domain socket listener
const defaultSocketPath = "/tmp/coder-agent.sock"
func createSocket(path string) (net.Listener, error) {
if path == "" {
path = defaultSocketPath
}
if !isSocketAvailable(path) {
return nil, xerrors.Errorf("socket path %s is not available", path)
}
@@ -23,7 +27,6 @@ func createSocket(path string) (net.Listener, error) {
return nil, xerrors.Errorf("remove existing socket: %w", err)
}
// Create parent directory if it doesn't exist
parentDir := filepath.Dir(path)
if err := os.MkdirAll(parentDir, 0o700); err != nil {
return nil, xerrors.Errorf("create socket directory: %w", err)
@@ -41,43 +44,30 @@ func createSocket(path string) (net.Listener, error) {
return listener, nil
}
// getDefaultSocketPath returns the default socket path for Unix-like systems
func getDefaultSocketPath() (string, error) {
randomBytes := make([]byte, 4)
if _, err := rand.Read(randomBytes); err != nil {
return "", xerrors.Errorf("generate random socket name: %w", err)
}
randomSuffix := hex.EncodeToString(randomBytes)
// Try XDG_RUNTIME_DIR first
if runtimeDir := os.Getenv("XDG_RUNTIME_DIR"); runtimeDir != "" {
return filepath.Join(runtimeDir, "coder-agent-"+randomSuffix+".sock"), nil
}
return filepath.Join("/tmp", "coder-agent-"+randomSuffix+".sock"), nil
}
// CleanupSocket removes the socket file
func cleanupSocket(path string) error {
return os.Remove(path)
}
// isSocketAvailable checks if a socket path is available for use
func isSocketAvailable(path string) bool {
// Check if file exists
if _, err := os.Stat(path); os.IsNotExist(err) {
return true
}
// Try to connect to see if it's actually listening
// Try to connect to see if it's actually listening.
dialer := net.Dialer{Timeout: 10 * time.Second}
conn, err := dialer.Dial("unix", path)
if err != nil {
// If we can't connect, the socket is not in use
// Socket is available for use
return true
}
_ = conn.Close()
// Socket is in use
return false
}
func dialSocket(ctx context.Context, path string) (net.Conn, error) {
if path == "" {
path = defaultSocketPath
}
dialer := net.Dialer{}
return dialer.DialContext(ctx, "unix", path)
}
+5 -10
View File
@@ -3,25 +3,20 @@
package agentsocket
import (
"context"
"net"
"golang.org/x/xerrors"
)
// createSocket returns an error indicating that agentsocket is not supported on Windows.
// This feature is unix-only in its current experimental state.
func createSocket(_ string) (net.Listener, error) {
return nil, xerrors.New("agentsocket is not supported on Windows")
}
// getDefaultSocketPath returns an error indicating that agentsocket is not supported on Windows.
// This feature is unix-only in its current experimental state.
func getDefaultSocketPath() (string, error) {
return "", xerrors.New("agentsocket is not supported on Windows")
}
// cleanupSocket is a no-op on Windows since agentsocket is not supported.
func cleanupSocket(_ string) error {
// No-op since agentsocket is not supported on Windows
return nil
}
func dialSocket(_ context.Context, _ string) (net.Conn, error) {
return nil, xerrors.New("agentsocket is not supported on Windows")
}
+11 -2
View File
@@ -391,10 +391,19 @@ func (s *Server) sessionHandler(session ssh.Session) {
env := session.Environ()
magicType, magicTypeRaw, env := extractMagicSessionType(env)
// It's not safe to assume RemoteAddr() returns a non-nil value. slog.F usage is fine because it correctly
// handles nil.
// c.f. https://github.com/coder/internal/issues/1143
remoteAddr := session.RemoteAddr()
remoteAddrString := ""
if remoteAddr != nil {
remoteAddrString = remoteAddr.String()
}
if !s.trackSession(session, true) {
reason := "unable to accept new session, server is closing"
// Report connection attempt even if we couldn't accept it.
disconnected := s.config.ReportConnection(id, magicType, session.RemoteAddr().String())
disconnected := s.config.ReportConnection(id, magicType, remoteAddrString)
defer disconnected(1, reason)
logger.Info(ctx, reason)
@@ -429,7 +438,7 @@ func (s *Server) sessionHandler(session ssh.Session) {
scr := &sessionCloseTracker{Session: session}
session = scr
disconnected := s.config.ReportConnection(id, magicType, session.RemoteAddr().String())
disconnected := s.config.ReportConnection(id, magicType, remoteAddrString)
defer func() {
disconnected(scr.exitCode(), reason)
}()
+1 -1
View File
@@ -176,7 +176,7 @@ func (x *x11Forwarder) listenForConnections(
var originPort uint32
if tcpConn, ok := conn.(*net.TCPConn); ok {
if tcpAddr, ok := tcpConn.LocalAddr().(*net.TCPAddr); ok {
if tcpAddr, ok := tcpConn.LocalAddr().(*net.TCPAddr); ok && tcpAddr != nil {
originAddr = tcpAddr.IP.String()
// #nosec G115 - Safe conversion as TCP port numbers are within uint32 range (0-65535)
originPort = uint32(tcpAddr.Port)
+33 -31
View File
@@ -2,41 +2,31 @@ package agent
import (
"net/http"
"sync"
"time"
"github.com/go-chi/chi/v5"
"github.com/google/uuid"
"github.com/coder/coder/v2/coderd/httpapi"
"github.com/coder/coder/v2/coderd/httpmw/loggermw"
"github.com/coder/coder/v2/coderd/tracing"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/workspacesdk"
"github.com/coder/coder/v2/httpmw"
)
func (a *agent) apiHandler() http.Handler {
r := chi.NewRouter()
r.Use(
httpmw.Recover(a.logger),
tracing.StatusWriterMiddleware,
loggermw.Logger(a.logger),
)
r.Get("/", func(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.Response{
Message: "Hello from the agent!",
})
})
// Make a copy to ensure the map is not modified after the handler is
// created.
cpy := make(map[int]string)
for k, b := range a.ignorePorts {
cpy[k] = b
}
cacheDuration := 1 * time.Second
if a.portCacheDuration > 0 {
cacheDuration = a.portCacheDuration
}
lp := &listeningPortsHandler{
ignorePorts: cpy,
cacheDuration: cacheDuration,
}
if a.devcontainers {
r.Mount("/api/v0/containers", a.containerAPI.Routes())
} else if manifest := a.manifest.Load(); manifest != nil && manifest.ParentID != uuid.Nil {
@@ -57,7 +47,7 @@ func (a *agent) apiHandler() http.Handler {
promHandler := PrometheusMetricsHandler(a.prometheusRegistry, a.logger)
r.Get("/api/v0/listening-ports", lp.handler)
r.Get("/api/v0/listening-ports", a.listeningPortsHandler.handler)
r.Get("/api/v0/netcheck", a.HandleNetcheck)
r.Post("/api/v0/list-directory", a.HandleLS)
r.Get("/api/v0/read-file", a.HandleReadFile)
@@ -72,22 +62,21 @@ func (a *agent) apiHandler() http.Handler {
return r
}
type listeningPortsHandler struct {
ignorePorts map[int]string
cacheDuration time.Duration
type ListeningPortsGetter interface {
GetListeningPorts() ([]codersdk.WorkspaceAgentListeningPort, error)
}
//nolint: unused // used on some but not all platforms
mut sync.Mutex
//nolint: unused // used on some but not all platforms
ports []codersdk.WorkspaceAgentListeningPort
//nolint: unused // used on some but not all platforms
mtime time.Time
type listeningPortsHandler struct {
// In production code, this is set to an osListeningPortsGetter, but it can be overridden for
// testing.
getter ListeningPortsGetter
ignorePorts map[int]string
}
// handler returns a list of listening ports. This is tested by coderd's
// TestWorkspaceAgentListeningPorts test.
func (lp *listeningPortsHandler) handler(rw http.ResponseWriter, r *http.Request) {
ports, err := lp.getListeningPorts()
ports, err := lp.getter.GetListeningPorts()
if err != nil {
httpapi.Write(r.Context(), rw, http.StatusInternalServerError, codersdk.Response{
Message: "Could not scan for listening ports.",
@@ -96,7 +85,20 @@ func (lp *listeningPortsHandler) handler(rw http.ResponseWriter, r *http.Request
return
}
filteredPorts := make([]codersdk.WorkspaceAgentListeningPort, 0, len(ports))
for _, port := range ports {
if port.Port < workspacesdk.AgentMinimumListeningPort {
continue
}
// Ignore ports that we've been told to ignore.
if _, ok := lp.ignorePorts[int(port.Port)]; ok {
continue
}
filteredPorts = append(filteredPorts, port)
}
httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.WorkspaceAgentListeningPortsResponse{
Ports: ports,
Ports: filteredPorts,
})
}
+10 -8
View File
@@ -3,16 +3,23 @@
package agent
import (
"sync"
"time"
"github.com/cakturk/go-netstat/netstat"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/workspacesdk"
)
func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentListeningPort, error) {
type osListeningPortsGetter struct {
cacheDuration time.Duration
mut sync.Mutex
ports []codersdk.WorkspaceAgentListeningPort
mtime time.Time
}
func (lp *osListeningPortsGetter) GetListeningPorts() ([]codersdk.WorkspaceAgentListeningPort, error) {
lp.mut.Lock()
defer lp.mut.Unlock()
@@ -33,12 +40,7 @@ func (lp *listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentL
seen := make(map[uint16]struct{}, len(tabs))
ports := []codersdk.WorkspaceAgentListeningPort{}
for _, tab := range tabs {
if tab.LocalAddr == nil || tab.LocalAddr.Port < workspacesdk.AgentMinimumListeningPort {
continue
}
// Ignore ports that we've been told to ignore.
if _, ok := lp.ignorePorts[int(tab.LocalAddr.Port)]; ok {
if tab.LocalAddr == nil {
continue
}
+45
View File
@@ -0,0 +1,45 @@
//go:build linux || (windows && amd64)
package agent
import (
"net"
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestOSListeningPortsGetter(t *testing.T) {
t.Parallel()
uut := &osListeningPortsGetter{
cacheDuration: 1 * time.Hour,
}
l, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
defer l.Close()
ports, err := uut.GetListeningPorts()
require.NoError(t, err)
found := false
for _, port := range ports {
// #nosec G115 - Safe conversion as TCP port numbers are within uint16 range (0-65535)
if port.Port == uint16(l.Addr().(*net.TCPAddr).Port) {
found = true
break
}
}
require.True(t, found)
// check that we cache the ports
err = l.Close()
require.NoError(t, err)
portsNew, err := uut.GetListeningPorts()
require.NoError(t, err)
require.Equal(t, ports, portsNew)
// note that it's unsafe to try to assert that a port does not exist in the response
// because the OS may reallocate the port very quickly.
}
+10 -2
View File
@@ -2,9 +2,17 @@
package agent
import "github.com/coder/coder/v2/codersdk"
import (
"time"
func (*listeningPortsHandler) getListeningPorts() ([]codersdk.WorkspaceAgentListeningPort, error) {
"github.com/coder/coder/v2/codersdk"
)
type osListeningPortsGetter struct {
cacheDuration time.Duration
}
func (*osListeningPortsGetter) GetListeningPorts() ([]codersdk.WorkspaceAgentListeningPort, error) {
// Can't scan for ports on non-linux or non-windows_amd64 systems at the
// moment. The UI will not show any "no ports found" message to the user, so
// the user won't suspect a thing.
+13 -3
View File
@@ -74,11 +74,21 @@ func (s *Server) Serve(ctx, hardCtx context.Context, l net.Listener) (retErr err
break
}
clog := s.logger.With(
slog.F("remote", conn.RemoteAddr().String()),
slog.F("local", conn.LocalAddr().String()))
slog.F("remote", conn.RemoteAddr()),
slog.F("local", conn.LocalAddr()))
clog.Info(ctx, "accepted conn")
// It's not safe to assume RemoteAddr() returns a non-nil value. slog.F usage is fine because it correctly
// handles nil.
// c.f. https://github.com/coder/internal/issues/1143
remoteAddr := conn.RemoteAddr()
remoteAddrString := ""
if remoteAddr != nil {
remoteAddrString = remoteAddr.String()
}
wg.Add(1)
disconnected := s.reportConnection(uuid.New(), conn.RemoteAddr().String())
disconnected := s.reportConnection(uuid.New(), remoteAddrString)
closed := make(chan struct{})
go func() {
defer wg.Done()
+11 -1
View File
@@ -2,6 +2,7 @@ package unit
import (
"errors"
"fmt"
"sync"
"golang.org/x/xerrors"
@@ -23,6 +24,15 @@ var (
// Status represents the status of a unit.
type Status string
var _ fmt.Stringer = Status("")
func (s Status) String() string {
if s == StatusNotRegistered {
return "not registered"
}
return string(s)
}
// Status constants for dependency tracking.
const (
StatusNotRegistered Status = ""
@@ -137,7 +147,7 @@ func (m *Manager) IsReady(id ID) (bool, error) {
defer m.mu.RUnlock()
if !m.registered(id) {
return false, nil
return true, nil
}
return m.units[id].ready, nil
+1 -1
View File
@@ -684,7 +684,7 @@ func TestManager_IsReady(t *testing.T) {
// Then: the unit is not ready
isReady, err := manager.IsReady(unitA)
require.NoError(t, err)
assert.False(t, isReady)
assert.True(t, isReady)
})
}
+17
View File
@@ -57,6 +57,8 @@ func workspaceAgent() *serpent.Command {
devcontainers bool
devcontainerProjectDiscovery bool
devcontainerDiscoveryAutostart bool
socketServerEnabled bool
socketPath string
)
agentAuth := &AgentAuth{}
cmd := &serpent.Command{
@@ -317,6 +319,8 @@ func workspaceAgent() *serpent.Command {
agentcontainers.WithProjectDiscovery(devcontainerProjectDiscovery),
agentcontainers.WithDiscoveryAutostart(devcontainerDiscoveryAutostart),
},
SocketPath: socketPath,
SocketServerEnabled: socketServerEnabled,
})
if debugAddress != "" {
@@ -477,6 +481,19 @@ func workspaceAgent() *serpent.Command {
Description: "Allow the agent to autostart devcontainer projects it discovers based on their configuration.",
Value: serpent.BoolOf(&devcontainerDiscoveryAutostart),
},
{
Flag: "socket-server-enabled",
Default: "false",
Env: "CODER_AGENT_SOCKET_SERVER_ENABLED",
Description: "Enable the agent socket server.",
Value: serpent.BoolOf(&socketServerEnabled),
},
{
Flag: "socket-path",
Env: "CODER_AGENT_SOCKET_PATH",
Description: "Specify the path for the agent socket.",
Value: serpent.StringOf(&socketPath),
},
}
agentAuth.AttachOptions(cmd, false)
return cmd
+20 -4
View File
@@ -28,7 +28,9 @@ import (
)
// New creates a CLI instance with a configuration pointed to a
// temporary testing directory.
// temporary testing directory. The invocation is set up to use a
// global config directory for the given testing.TB, and keyring
// usage disabled.
func New(t testing.TB, args ...string) (*serpent.Invocation, config.Root) {
var root cli.RootCmd
@@ -59,6 +61,15 @@ func NewWithCommand(
t testing.TB, cmd *serpent.Command, args ...string,
) (*serpent.Invocation, config.Root) {
configDir := config.Root(t.TempDir())
// Keyring usage is disabled here when --global-config is set because many existing
// tests expect the session token to be stored on disk and is not properly instrumented
// for parallel testing against the actual operating system keyring.
invArgs := append([]string{"--global-config", string(configDir)}, args...)
return setupInvocation(t, cmd, invArgs...), configDir
}
func setupInvocation(t testing.TB, cmd *serpent.Command, args ...string,
) *serpent.Invocation {
// I really would like to fail test on error logs, but realistically, turning on by default
// in all our CLI tests is going to create a lot of flaky noise.
logger := slogtest.Make(t, &slogtest.Options{IgnoreErrors: true}).
@@ -66,16 +77,21 @@ func NewWithCommand(
Named("cli")
i := &serpent.Invocation{
Command: cmd,
Args: append([]string{"--global-config", string(configDir)}, args...),
Args: args,
Stdin: io.LimitReader(nil, 0),
Stdout: (&logWriter{prefix: "stdout", log: logger}),
Stderr: (&logWriter{prefix: "stderr", log: logger}),
Logger: logger,
}
t.Logf("invoking command: %s %s", cmd.Name(), strings.Join(i.Args, " "))
return i
}
// These can be overridden by the test.
return i, configDir
func NewWithDefaultKeyringCommand(t testing.TB, cmd *serpent.Command, args ...string,
) (*serpent.Invocation, config.Root) {
configDir := config.Root(t.TempDir())
invArgs := append([]string{"--global-config", string(configDir)}, args...)
return setupInvocation(t, cmd, invArgs...), configDir
}
// SetupConfig applies the URL and SessionToken of the client to the config.
+3
View File
@@ -106,6 +106,9 @@ var _ OutputFormat = &tableFormat{}
//
// defaultColumns is optional and specifies the default columns to display. If
// not specified, all columns are displayed by default.
//
// If the data is empty, an empty string is returned. Callers should check for
// this and provide an appropriate message to the user.
func TableFormat(out any, defaultColumns []string) OutputFormat {
v := reflect.Indirect(reflect.ValueOf(out))
if v.Kind() != reflect.Slice {
+6
View File
@@ -180,6 +180,12 @@ func DisplayTable(out any, sort string, filterColumns []string) (string, error)
func renderTable(out any, sort string, headers table.Row, filterColumns []string) (string, error) {
v := reflect.Indirect(reflect.ValueOf(out))
// Return empty string for empty data. Callers should check for this
// and provide an appropriate message to the user.
if v.Kind() == reflect.Slice && v.Len() == 0 {
return "", nil
}
headers = filterHeaders(headers, filterColumns)
columnConfigs := createColumnConfigs(headers, filterColumns)
+9
View File
@@ -472,6 +472,15 @@ alice 1
require.NoError(t, err)
compareTables(t, expected, out)
})
t.Run("Empty", func(t *testing.T) {
t.Parallel()
var in []tableTest4
out, err := cliui.DisplayTable(in, "", nil)
require.NoError(t, err)
require.Empty(t, out)
})
}
// compareTables normalizes the incoming table lines
+3 -3
View File
@@ -90,7 +90,6 @@ func TestExpRpty(t *testing.T) {
wantLabel := "coder.devcontainers.TestExpRpty.Container"
client, workspace, agentToken := setupWorkspaceForAgent(t)
ctx := testutil.Context(t, testutil.WaitLong)
pool, err := dockertest.NewPool("")
require.NoError(t, err, "Could not connect to docker")
ct, err := pool.RunWithOptions(&dockertest.RunOptions{
@@ -128,14 +127,15 @@ func TestExpRpty(t *testing.T) {
clitest.SetupConfig(t, client, root)
pty := ptytest.New(t).Attach(inv)
ctx := testutil.Context(t, testutil.WaitLong)
cmdDone := tGo(t, func() {
err := inv.WithContext(ctx).Run()
assert.NoError(t, err)
})
pty.ExpectMatch(" #")
pty.ExpectMatchContext(ctx, " #")
pty.WriteLine("hostname")
pty.ExpectMatch(ct.Container.Config.Hostname)
pty.ExpectMatchContext(ctx, ct.Container.Config.Hostname)
pty.WriteLine("exit")
<-cmdDone
})
+10 -8
View File
@@ -1559,6 +1559,15 @@ func (r *RootCmd) scaletestDashboard() *serpent.Command {
if err != nil {
return xerrors.Errorf("create tracer provider: %w", err)
}
tracer := tracerProvider.Tracer(scaletestTracerName)
outputs, err := output.parse()
if err != nil {
return xerrors.Errorf("could not parse --output flags")
}
reg := prometheus.NewRegistry()
prometheusSrvClose := ServeHandler(ctx, logger, promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), prometheusFlags.Address, "prometheus")
defer prometheusSrvClose()
defer func() {
// Allow time for traces to flush even if command context is
// canceled. This is a no-op if tracing is not enabled.
@@ -1570,14 +1579,7 @@ func (r *RootCmd) scaletestDashboard() *serpent.Command {
_, _ = fmt.Fprintf(inv.Stderr, "Waiting %s for prometheus metrics to be scraped\n", prometheusFlags.Wait)
<-time.After(prometheusFlags.Wait)
}()
tracer := tracerProvider.Tracer(scaletestTracerName)
outputs, err := output.parse()
if err != nil {
return xerrors.Errorf("could not parse --output flags")
}
reg := prometheus.NewRegistry()
prometheusSrvClose := ServeHandler(ctx, logger, promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), prometheusFlags.Address, "prometheus")
defer prometheusSrvClose()
metrics := dashboard.NewMetrics(reg)
th := harness.NewTestHarness(strategy.toStrategy(), cleanupStrategy.toStrategy())
+9 -8
View File
@@ -84,14 +84,6 @@ func (r *RootCmd) scaletestPrebuilds() *serpent.Command {
if err != nil {
return xerrors.Errorf("create tracer provider: %w", err)
}
defer func() {
_, _ = fmt.Fprintln(inv.Stderr, "\nUploading traces...")
if err := closeTracing(ctx); err != nil {
_, _ = fmt.Fprintf(inv.Stderr, "\nError uploading traces: %+v\n", err)
}
_, _ = fmt.Fprintf(inv.Stderr, "Waiting %s for prometheus metrics to be scraped\n", prometheusFlags.Wait)
<-time.After(prometheusFlags.Wait)
}()
tracer := tracerProvider.Tracer(scaletestTracerName)
reg := prometheus.NewRegistry()
@@ -101,6 +93,15 @@ func (r *RootCmd) scaletestPrebuilds() *serpent.Command {
prometheusSrvClose := ServeHandler(ctx, logger, promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), prometheusFlags.Address, "prometheus")
defer prometheusSrvClose()
defer func() {
_, _ = fmt.Fprintln(inv.Stderr, "\nUploading traces...")
if err := closeTracing(ctx); err != nil {
_, _ = fmt.Fprintf(inv.Stderr, "\nError uploading traces: %+v\n", err)
}
_, _ = fmt.Fprintf(inv.Stderr, "Waiting %s for prometheus metrics to be scraped\n", prometheusFlags.Wait)
<-time.After(prometheusFlags.Wait)
}()
err = client.PutPrebuildsSettings(ctx, codersdk.PrebuildsSettings{
ReconciliationPaused: true,
})
+204 -133
View File
@@ -2,62 +2,85 @@ package cli_test
import (
"bytes"
"crypto/rand"
"encoding/binary"
"fmt"
"net/url"
"os"
"path"
"runtime"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/cli/sessionstore"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
"github.com/coder/serpent"
)
// mockKeyring is a mock sessionstore.Backend implementation.
type mockKeyring struct {
credentials map[string]string // service name -> credential
}
const mockServiceName = "mock-service-name"
func newMockKeyring() *mockKeyring {
return &mockKeyring{credentials: make(map[string]string)}
}
func (m *mockKeyring) Read(_ *url.URL) (string, error) {
cred, ok := m.credentials[mockServiceName]
if !ok {
return "", os.ErrNotExist
// keyringTestServiceName generates a unique service name for keyring tests
// using the test name and a nanosecond timestamp to prevent collisions.
func keyringTestServiceName(t *testing.T) string {
t.Helper()
var n uint32
err := binary.Read(rand.Reader, binary.BigEndian, &n)
if err != nil {
t.Fatal(err)
}
return cred, nil
return fmt.Sprintf("%s_%v_%d", t.Name(), time.Now().UnixNano(), n)
}
func (m *mockKeyring) Write(_ *url.URL, token string) error {
m.credentials[mockServiceName] = token
return nil
type keyringTestEnv struct {
serviceName string
keyring sessionstore.Keyring
inv *serpent.Invocation
cfg config.Root
clientURL *url.URL
}
func (m *mockKeyring) Delete(_ *url.URL) error {
_, ok := m.credentials[mockServiceName]
if !ok {
return os.ErrNotExist
}
delete(m.credentials, mockServiceName)
return nil
func setupKeyringTestEnv(t *testing.T, clientURL string, args ...string) keyringTestEnv {
t.Helper()
var root cli.RootCmd
cmd, err := root.Command(root.AGPL())
require.NoError(t, err)
serviceName := keyringTestServiceName(t)
root.WithKeyringServiceName(serviceName)
root.UseKeyringWithGlobalConfig()
inv, cfg := clitest.NewWithDefaultKeyringCommand(t, cmd, args...)
parsedURL, err := url.Parse(clientURL)
require.NoError(t, err)
backend := sessionstore.NewKeyringWithService(serviceName)
t.Cleanup(func() {
_ = backend.Delete(parsedURL)
})
return keyringTestEnv{serviceName, backend, inv, cfg, parsedURL}
}
func TestUseKeyring(t *testing.T) {
// Verify that the --use-keyring flag opts into using a keyring backend for
// storing session tokens instead of plain text files.
// Verify that the --use-keyring flag default opts into using a keyring backend
// for storing session tokens instead of plain text files.
t.Parallel()
t.Run("Login", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
t.Skip("keyring is not supported on this OS")
}
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
@@ -65,25 +88,16 @@ func TestUseKeyring(t *testing.T) {
// Create a pty for interactive prompts
pty := ptytest.New(t)
// Create CLI invocation with --use-keyring flag
inv, cfg := clitest.New(t,
// Create CLI invocation which defaults to using the keyring
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--force-tty",
"--use-keyring",
"--no-open",
client.URL.String(),
)
client.URL.String())
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
// Inject the mock backend before running the command
var root cli.RootCmd
cmd, err := root.Command(root.AGPL())
require.NoError(t, err)
mockBackend := newMockKeyring()
root.WithSessionStorageBackend(mockBackend)
inv.Command = cmd
// Run login in background
doneChan := make(chan struct{})
go func() {
@@ -99,19 +113,23 @@ func TestUseKeyring(t *testing.T) {
<-doneChan
// Verify that session file was NOT created (using keyring instead)
sessionFile := path.Join(string(cfg), "session")
_, err = os.Stat(sessionFile)
sessionFile := path.Join(string(env.cfg), "session")
_, err := os.Stat(sessionFile)
require.True(t, os.IsNotExist(err), "session file should not exist when using keyring")
// Verify that the credential IS stored in mock keyring
cred, err := mockBackend.Read(nil)
require.NoError(t, err, "credential should be stored in mock keyring")
// Verify that the credential IS stored in OS keyring
cred, err := env.keyring.Read(env.clientURL)
require.NoError(t, err, "credential should be stored in OS keyring")
require.Equal(t, client.SessionToken(), cred, "stored token should match login token")
})
t.Run("Logout", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
t.Skip("keyring is not supported on this OS")
}
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
@@ -119,25 +137,17 @@ func TestUseKeyring(t *testing.T) {
// Create a pty for interactive prompts
pty := ptytest.New(t)
// First, login with --use-keyring
loginInv, cfg := clitest.New(t,
// First, login with the keyring (default)
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--force-tty",
"--use-keyring",
"--no-open",
client.URL.String(),
)
loginInv := env.inv
loginInv.Stdin = pty.Input()
loginInv.Stdout = pty.Output()
// Inject the mock backend
var loginRoot cli.RootCmd
loginCmd, err := loginRoot.Command(loginRoot.AGPL())
require.NoError(t, err)
mockBackend := newMockKeyring()
loginRoot.WithSessionStorageBackend(mockBackend)
loginInv.Command = loginCmd
doneChan := make(chan struct{})
go func() {
defer close(doneChan)
@@ -150,25 +160,23 @@ func TestUseKeyring(t *testing.T) {
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Verify credential exists in mock keyring
cred, err := mockBackend.Read(nil)
// Verify credential exists in OS keyring
cred, err := env.keyring.Read(env.clientURL)
require.NoError(t, err, "read credential should succeed before logout")
require.NotEmpty(t, cred, "credential should exist after logout")
require.NotEmpty(t, cred, "credential should exist before logout")
// Now run logout with --use-keyring
logoutInv, _ := clitest.New(t,
"logout",
"--use-keyring",
"--yes",
"--global-config", string(cfg),
)
// Inject the same mock backend
// Now logout using the same keyring service name
var logoutRoot cli.RootCmd
logoutCmd, err := logoutRoot.Command(logoutRoot.AGPL())
require.NoError(t, err)
logoutRoot.WithSessionStorageBackend(mockBackend)
logoutInv.Command = logoutCmd
logoutRoot.WithKeyringServiceName(env.serviceName)
logoutRoot.UseKeyringWithGlobalConfig()
logoutInv, _ := clitest.NewWithDefaultKeyringCommand(t, logoutCmd,
"logout",
"--yes",
"--global-config", string(env.cfg),
)
var logoutOut bytes.Buffer
logoutInv.Stdout = &logoutOut
@@ -176,14 +184,18 @@ func TestUseKeyring(t *testing.T) {
err = logoutInv.Run()
require.NoError(t, err, "logout should succeed")
// Verify the credential was deleted from mock keyring
_, err = mockBackend.Read(nil)
// Verify the credential was deleted from OS keyring
_, err = env.keyring.Read(env.clientURL)
require.ErrorIs(t, err, os.ErrNotExist, "credential should be deleted from keyring after logout")
})
t.Run("OmitFlag", func(t *testing.T) {
t.Run("DefaultFileStorage", func(t *testing.T) {
t.Parallel()
if runtime.GOOS != "linux" {
t.Skip("file storage is the default for Linux")
}
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
@@ -191,13 +203,13 @@ func TestUseKeyring(t *testing.T) {
// Create a pty for interactive prompts
pty := ptytest.New(t)
// --use-keyring flag omitted (should use file-based storage)
inv, cfg := clitest.New(t,
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--force-tty",
"--no-open",
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
@@ -214,9 +226,9 @@ func TestUseKeyring(t *testing.T) {
<-doneChan
// Verify that session file WAS created (not using keyring)
sessionFile := path.Join(string(cfg), "session")
sessionFile := path.Join(string(env.cfg), "session")
_, err := os.Stat(sessionFile)
require.NoError(t, err, "session file should exist when NOT using --use-keyring")
require.NoError(t, err, "session file should exist when NOT using --use-keyring on Linux")
// Read and verify the token from file
content, err := os.ReadFile(sessionFile)
@@ -234,24 +246,18 @@ func TestUseKeyring(t *testing.T) {
// Create a pty for interactive prompts
pty := ptytest.New(t)
// Login using CODER_USE_KEYRING environment variable instead of flag
inv, cfg := clitest.New(t,
// Login using CODER_USE_KEYRING environment variable set to disable keyring usage,
// which should have the same behavior on all platforms.
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--force-tty",
"--no-open",
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
inv.Environ.Set("CODER_USE_KEYRING", "true")
// Inject the mock backend
var root cli.RootCmd
cmd, err := root.Command(root.AGPL())
require.NoError(t, err)
mockBackend := newMockKeyring()
root.WithSessionStorageBackend(mockBackend)
inv.Command = cmd
inv.Environ.Set("CODER_USE_KEYRING", "false")
doneChan := make(chan struct{})
go func() {
@@ -265,21 +271,64 @@ func TestUseKeyring(t *testing.T) {
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Verify that session file was NOT created (using keyring via env var)
sessionFile := path.Join(string(cfg), "session")
_, err = os.Stat(sessionFile)
require.True(t, os.IsNotExist(err), "session file should not exist when using keyring via env var")
// Verify that session file WAS created (not using keyring)
sessionFile := path.Join(string(env.cfg), "session")
_, err := os.Stat(sessionFile)
require.NoError(t, err, "session file should exist when CODER_USE_KEYRING set to false")
// Verify credential is in mock keyring
cred, err := mockBackend.Read(nil)
require.NoError(t, err, "credential should be stored in keyring when CODER_USE_KEYRING=true")
require.NotEmpty(t, cred)
// Read and verify the token from file
content, err := os.ReadFile(sessionFile)
require.NoError(t, err, "should be able to read session file")
require.Equal(t, client.SessionToken(), string(content), "file should contain the session token")
})
t.Run("DisableKeyringWithFlag", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
pty := ptytest.New(t)
// Login with --use-keyring=false to explicitly disable keyring usage, which
// should have the same behavior on all platforms.
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--use-keyring=false",
"--force-tty",
"--no-open",
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
doneChan := make(chan struct{})
go func() {
defer close(doneChan)
err := inv.Run()
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Verify that session file WAS created (not using keyring)
sessionFile := path.Join(string(env.cfg), "session")
_, err := os.Stat(sessionFile)
require.NoError(t, err, "session file should exist when --use-keyring=false is specified")
// Read and verify the token from file
content, err := os.ReadFile(sessionFile)
require.NoError(t, err, "should be able to read session file")
require.Equal(t, client.SessionToken(), string(content), "file should contain the session token")
})
}
func TestUseKeyringUnsupportedOS(t *testing.T) {
// Verify that trying to use --use-keyring on an unsupported operating system produces
// a helpful error message.
// Verify that on unsupported operating systems, file-based storage is used
// automatically even when --use-keyring is set to true (the default).
t.Parallel()
// Only run this on an unsupported OS.
@@ -287,43 +336,60 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
t.Skipf("Skipping unsupported OS test on %s where keyring is supported", runtime.GOOS)
}
const expMessage = "keyring storage is not supported on this operating system; remove the --use-keyring flag"
t.Run("LoginWithUnsupportedKeyring", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Try to login with --use-keyring on an unsupported OS
inv, _ := clitest.New(t,
"login",
"--use-keyring",
client.URL.String(),
)
// The error should occur immediately, before any prompts
loginErr := inv.Run()
// Verify we got an error about unsupported OS
require.Error(t, loginErr)
require.Contains(t, loginErr.Error(), expMessage)
})
t.Run("LogoutWithUnsupportedKeyring", func(t *testing.T) {
t.Run("LoginWithDefaultKeyring", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
pty := ptytest.New(t)
// First login without keyring to create a session
loginInv, cfg := clitest.New(t,
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--force-tty",
"--no-open",
client.URL.String(),
)
inv := env.inv
inv.Stdin = pty.Input()
inv.Stdout = pty.Output()
doneChan := make(chan struct{})
go func() {
defer close(doneChan)
err := inv.Run()
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Verify that session file WAS created (automatic fallback to file storage)
sessionFile := path.Join(string(env.cfg), "session")
_, err := os.Stat(sessionFile)
require.NoError(t, err, "session file should exist due to automatic fallback to file storage")
content, err := os.ReadFile(sessionFile)
require.NoError(t, err, "should be able to read session file")
require.Equal(t, client.SessionToken(), string(content), "file should contain the session token")
})
t.Run("LogoutWithDefaultKeyring", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
pty := ptytest.New(t)
// First login to create a session (will use file storage due to automatic fallback)
env := setupKeyringTestEnv(t, client.URL.String(),
"login",
"--force-tty",
"--no-open",
client.URL.String(),
)
loginInv := env.inv
loginInv.Stdin = pty.Input()
loginInv.Stdout = pty.Output()
@@ -339,17 +405,22 @@ func TestUseKeyringUnsupportedOS(t *testing.T) {
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Now try to logout with --use-keyring on an unsupported OS
logoutInv, _ := clitest.New(t,
// Verify session file exists
sessionFile := path.Join(string(env.cfg), "session")
_, err := os.Stat(sessionFile)
require.NoError(t, err, "session file should exist before logout")
// Now logout - should succeed and delete the file
logoutEnv := setupKeyringTestEnv(t, client.URL.String(),
"logout",
"--use-keyring",
"--yes",
"--global-config", string(cfg),
"--global-config", string(env.cfg),
)
err := logoutInv.Run()
// Verify we got an error about unsupported OS
require.Error(t, err)
require.Contains(t, err.Error(), expMessage)
err = logoutEnv.inv.Run()
require.NoError(t, err, "logout should succeed with automatic file storage fallback")
_, err = os.Stat(sessionFile)
require.True(t, os.IsNotExist(err), "session file should be deleted after logout")
})
}
+6 -6
View File
@@ -139,7 +139,12 @@ func (r *RootCmd) list() *serpent.Command {
return err
}
if len(res) == 0 && formatter.FormatID() != cliui.JSONFormat().ID() {
out, err := formatter.Format(inv.Context(), res)
if err != nil {
return err
}
if out == "" {
pretty.Fprintf(inv.Stderr, cliui.DefaultStyles.Prompt, "No workspaces found! Create one:\n")
_, _ = fmt.Fprintln(inv.Stderr)
_, _ = fmt.Fprintln(inv.Stderr, " "+pretty.Sprint(cliui.DefaultStyles.Code, "coder create <name>"))
@@ -147,11 +152,6 @@ func (r *RootCmd) list() *serpent.Command {
return nil
}
out, err := formatter.Format(inv.Context(), res)
if err != nil {
return err
}
_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
+3 -3
View File
@@ -154,9 +154,9 @@ func (r *RootCmd) login() *serpent.Command {
cmd := &serpent.Command{
Use: "login [<url>]",
Short: "Authenticate with Coder deployment",
Long: "By default, the session token is stored in a plain text file. Use the " +
"--use-keyring flag or set CODER_USE_KEYRING=true to store the token in " +
"the operating system keyring instead.",
Long: "By default, the session token is stored in the operating system keyring on " +
"macOS and Windows and a plain text file on Linux. Use the --use-keyring flag " +
"or CODER_USE_KEYRING environment variable to change the storage mechanism.",
Middleware: serpent.RequireRangeArgs(0, 1),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
+5
View File
@@ -170,6 +170,11 @@ func (r *RootCmd) listOrganizationMembers(orgContext *OrganizationContext) *serp
return err
}
if out == "" {
cliui.Infof(inv.Stderr, "No organization members found.")
return nil
}
_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
+5
View File
@@ -92,6 +92,11 @@ func (r *RootCmd) showOrganizationRoles(orgContext *OrganizationContext) *serpen
return err
}
if out == "" {
cliui.Infof(inv.Stderr, "No organization roles found.")
return nil
}
_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
+5
View File
@@ -110,6 +110,11 @@ func (r *RootCmd) provisionerJobsList() *serpent.Command {
return xerrors.Errorf("display provisioner daemons: %w", err)
}
if out == "" {
cliui.Infof(inv.Stderr, "No provisioner jobs found.")
return nil
}
_, _ = fmt.Fprintln(inv.Stdout, out)
return nil
+5 -5
View File
@@ -74,11 +74,6 @@ func (r *RootCmd) provisionerList() *serpent.Command {
return xerrors.Errorf("list provisioner daemons: %w", err)
}
if len(daemons) == 0 {
_, _ = fmt.Fprintln(inv.Stdout, "No provisioner daemons found")
return nil
}
var rows []provisionerDaemonRow
for _, daemon := range daemons {
rows = append(rows, provisionerDaemonRow{
@@ -92,6 +87,11 @@ func (r *RootCmd) provisionerList() *serpent.Command {
return xerrors.Errorf("display provisioner daemons: %w", err)
}
if out == "" {
cliui.Infof(inv.Stderr, "No provisioner daemons found.")
return nil
}
_, _ = fmt.Fprintln(inv.Stdout, out)
return nil
+40 -14
View File
@@ -56,7 +56,7 @@ var (
// anything.
ErrSilent = xerrors.New("silent error")
errKeyringNotSupported = xerrors.New("keyring storage is not supported on this operating system; remove the --use-keyring flag to use file-based storage")
errKeyringNotSupported = xerrors.New("keyring storage is not supported on this operating system; omit --use-keyring to use file-based storage")
)
const (
@@ -104,6 +104,7 @@ func (r *RootCmd) CoreSubcommands() []*serpent.Command {
r.resetPassword(),
r.sharing(),
r.state(),
r.tasksCommand(),
r.templates(),
r.tokens(),
r.users(),
@@ -149,7 +150,7 @@ func (r *RootCmd) AGPLExperimental() []*serpent.Command {
r.mcpCommand(),
r.promptExample(),
r.rptyCommand(),
r.tasksCommand(),
r.syncCommand(),
r.boundary(),
}
}
@@ -483,10 +484,12 @@ func (r *RootCmd) Command(subcommands []*serpent.Command) (*serpent.Command, err
Flag: varUseKeyring,
Env: envUseKeyring,
Description: "Store and retrieve session tokens using the operating system " +
"keyring. Currently only supported on Windows. By default, tokens are " +
"stored in plain text files.",
Value: serpent.BoolOf(&r.useKeyring),
Group: globalGroup,
"keyring. This flag is ignored and file-based storage is used when " +
"--global-config is set or keyring usage is not supported on the current " +
"platform. Set to false to force file-based storage on supported platforms.",
Default: "true",
Value: serpent.BoolOf(&r.useKeyring),
Group: globalGroup,
},
{
Flag: "debug-http",
@@ -534,10 +537,12 @@ type RootCmd struct {
disableDirect bool
debugHTTP bool
disableNetworkTelemetry bool
noVersionCheck bool
noFeatureWarning bool
useKeyring bool
disableNetworkTelemetry bool
noVersionCheck bool
noFeatureWarning bool
useKeyring bool
keyringServiceName string
useKeyringWithGlobalConfig bool
}
// InitClient creates and configures a new client with authentication, telemetry,
@@ -718,8 +723,19 @@ func (r *RootCmd) createUnauthenticatedClient(ctx context.Context, serverURL *ur
// flag.
func (r *RootCmd) ensureTokenBackend() sessionstore.Backend {
if r.tokenBackend == nil {
if r.useKeyring {
r.tokenBackend = sessionstore.NewKeyring()
// Checking for the --global-config directory being set is a bit wonky but necessary
// to allow extensions that invoke the CLI with this flag (e.g. VS code) to continue
// working without modification. In the future we should modify these extensions to
// either access the credential in the keyring (like Coder Desktop) or some other
// approach that doesn't rely on the session token being stored on disk.
assumeExtensionInUse := r.globalConfig != config.DefaultDir() && !r.useKeyringWithGlobalConfig
keyringSupported := runtime.GOOS == "windows" || runtime.GOOS == "darwin"
if r.useKeyring && !assumeExtensionInUse && keyringSupported {
serviceName := sessionstore.DefaultServiceName
if r.keyringServiceName != "" {
serviceName = r.keyringServiceName
}
r.tokenBackend = sessionstore.NewKeyringWithService(serviceName)
} else {
r.tokenBackend = sessionstore.NewFile(r.createConfig)
}
@@ -727,8 +743,18 @@ func (r *RootCmd) ensureTokenBackend() sessionstore.Backend {
return r.tokenBackend
}
func (r *RootCmd) WithSessionStorageBackend(backend sessionstore.Backend) {
r.tokenBackend = backend
// WithKeyringServiceName sets a custom keyring service name for testing purposes.
// This allows tests to use isolated keyring storage while still exercising the
// genuine storage backend selection logic in ensureTokenBackend().
func (r *RootCmd) WithKeyringServiceName(serviceName string) {
r.keyringServiceName = serviceName
}
// UseKeyringWithGlobalConfig enables the use of the keyring storage backend
// when the --global-config directory is set. This is only intended as an override
// for tests, which require specifying the global config directory for test isolation.
func (r *RootCmd) UseKeyringWithGlobalConfig() {
r.useKeyringWithGlobalConfig = true
}
type AgentAuth struct {
+25
View File
@@ -72,6 +72,31 @@ func TestCommandHelp(t *testing.T) {
Name: "coder provisioner jobs list --output json",
Cmd: []string{"provisioner", "jobs", "list", "--output", "json"},
},
// TODO (SasSwart): Remove these once the sync commands are promoted out of experimental.
clitest.CommandHelpCase{
Name: "coder exp sync --help",
Cmd: []string{"exp", "sync", "--help"},
},
clitest.CommandHelpCase{
Name: "coder exp sync ping --help",
Cmd: []string{"exp", "sync", "ping", "--help"},
},
clitest.CommandHelpCase{
Name: "coder exp sync start --help",
Cmd: []string{"exp", "sync", "start", "--help"},
},
clitest.CommandHelpCase{
Name: "coder exp sync want --help",
Cmd: []string{"exp", "sync", "want", "--help"},
},
clitest.CommandHelpCase{
Name: "coder exp sync complete --help",
Cmd: []string{"exp", "sync", "complete", "--help"},
},
clitest.CommandHelpCase{
Name: "coder exp sync status --help",
Cmd: []string{"exp", "sync", "status", "--help"},
},
))
}
+5
View File
@@ -129,6 +129,11 @@ func (r *RootCmd) scheduleShow() *serpent.Command {
return err
}
if out == "" {
cliui.Infof(inv.Stderr, "No schedules found.")
return nil
}
_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
+4 -12
View File
@@ -47,9 +47,9 @@ var (
)
const (
// defaultServiceName is the service name used in keyrings for storing Coder CLI session
// DefaultServiceName is the service name used in keyrings for storing Coder CLI session
// tokens.
defaultServiceName = "coder-v2-credentials"
DefaultServiceName = "coder-v2-credentials"
)
// keyringProvider represents an operating system keyring. The expectation
@@ -108,17 +108,9 @@ type Keyring struct {
serviceName string
}
// NewKeyring creates a Keyring with the default service name for production use.
func NewKeyring() Keyring {
return Keyring{
provider: operatingSystemKeyring{},
serviceName: defaultServiceName,
}
}
// NewKeyringWithService creates a Keyring Backend that stores credentials under the
// specified service name. This is primarily intended for testing to avoid conflicts
// with production credentials and collisions between tests.
// specified service name. Generally, DefaultServiceName should be provided as the service
// name except in tests which may need parameterization to avoid conflicting keyring use.
func NewKeyringWithService(serviceName string) Keyring {
return Keyring{
provider: operatingSystemKeyring{},
+3 -3
View File
@@ -2052,7 +2052,6 @@ func TestSSH_Container(t *testing.T) {
t.Parallel()
client, workspace, agentToken := setupWorkspaceForAgent(t)
ctx := testutil.Context(t, testutil.WaitLong)
pool, err := dockertest.NewPool("")
require.NoError(t, err, "Could not connect to docker")
ct, err := pool.RunWithOptions(&dockertest.RunOptions{
@@ -2087,14 +2086,15 @@ func TestSSH_Container(t *testing.T) {
clitest.SetupConfig(t, client, root)
ptty := ptytest.New(t).Attach(inv)
ctx := testutil.Context(t, testutil.WaitLong)
cmdDone := tGo(t, func() {
err := inv.WithContext(ctx).Run()
assert.NoError(t, err)
})
ptty.ExpectMatch(" #")
ptty.ExpectMatchContext(ctx, " #")
ptty.WriteLine("hostname")
ptty.ExpectMatch(ct.Container.Config.Hostname)
ptty.ExpectMatchContext(ctx, ct.Container.Config.Hostname)
ptty.WriteLine("exit")
<-cmdDone
})
+35
View File
@@ -0,0 +1,35 @@
package cli
import (
"github.com/coder/serpent"
)
func (r *RootCmd) syncCommand() *serpent.Command {
var socketPath string
cmd := &serpent.Command{
Use: "sync",
Short: "Manage unit dependencies for coordinated startup",
Long: "Commands for orchestrating unit startup order in workspaces. Units are most commonly coder scripts. Use these commands to declare dependencies between units, coordinate their startup sequence, and ensure units start only after their dependencies are ready. This helps prevent race conditions and startup failures.",
Handler: func(i *serpent.Invocation) error {
return i.Command.HelpHandler(i)
},
Children: []*serpent.Command{
r.syncPing(&socketPath),
r.syncStart(&socketPath),
r.syncWant(&socketPath),
r.syncComplete(&socketPath),
r.syncStatus(&socketPath),
},
Options: serpent.OptionSet{
{
Flag: "socket-path",
Env: "CODER_AGENT_SOCKET_PATH",
Description: "Specify the path for the agent socket.",
Value: serpent.StringOf(&socketPath),
},
},
}
return cmd
}
+47
View File
@@ -0,0 +1,47 @@
package cli
import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/unit"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/serpent"
)
func (*RootCmd) syncComplete(socketPath *string) *serpent.Command {
cmd := &serpent.Command{
Use: "complete <unit>",
Short: "Mark a unit as complete",
Long: "Mark a unit as complete. Indicating to other units that it has completed its work. This allows units that depend on it to proceed with their startup.",
Handler: func(i *serpent.Invocation) error {
ctx := i.Context()
if len(i.Args) != 1 {
return xerrors.New("exactly one unit name is required")
}
unit := unit.ID(i.Args[0])
opts := []agentsocket.Option{}
if *socketPath != "" {
opts = append(opts, agentsocket.WithPath(*socketPath))
}
client, err := agentsocket.NewClient(ctx, opts...)
if err != nil {
return xerrors.Errorf("connect to agent socket: %w", err)
}
defer client.Close()
if err := client.SyncComplete(ctx, unit); err != nil {
return xerrors.Errorf("complete unit failed: %w", err)
}
cliui.Info(i.Stdout, "Success")
return nil
},
}
return cmd
}
+42
View File
@@ -0,0 +1,42 @@
package cli
import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/serpent"
)
func (*RootCmd) syncPing(socketPath *string) *serpent.Command {
cmd := &serpent.Command{
Use: "ping",
Short: "Test agent socket connectivity and health",
Long: "Test connectivity to the local Coder agent socket to verify the agent is running and responsive. Useful for troubleshooting startup issues or verifying the agent is accessible before running other sync commands.",
Handler: func(i *serpent.Invocation) error {
ctx := i.Context()
opts := []agentsocket.Option{}
if *socketPath != "" {
opts = append(opts, agentsocket.WithPath(*socketPath))
}
client, err := agentsocket.NewClient(ctx, opts...)
if err != nil {
return xerrors.Errorf("connect to agent socket: %w", err)
}
defer client.Close()
err = client.Ping(ctx)
if err != nil {
return xerrors.Errorf("ping failed: %w", err)
}
cliui.Info(i.Stdout, "Success")
return nil
},
}
return cmd
}
+101
View File
@@ -0,0 +1,101 @@
package cli
import (
"context"
"time"
"golang.org/x/xerrors"
"github.com/coder/serpent"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/unit"
"github.com/coder/coder/v2/cli/cliui"
)
const (
syncPollInterval = 1 * time.Second
)
func (*RootCmd) syncStart(socketPath *string) *serpent.Command {
var timeout time.Duration
cmd := &serpent.Command{
Use: "start <unit>",
Short: "Wait until all unit dependencies are satisfied",
Long: "Wait until all dependencies are satisfied, consider the unit to have started, then allow it to proceed. This command polls until dependencies are ready, then marks the unit as started.",
Handler: func(i *serpent.Invocation) error {
ctx := i.Context()
if len(i.Args) != 1 {
return xerrors.New("exactly one unit name is required")
}
unitName := unit.ID(i.Args[0])
if timeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, timeout)
defer cancel()
}
opts := []agentsocket.Option{}
if *socketPath != "" {
opts = append(opts, agentsocket.WithPath(*socketPath))
}
client, err := agentsocket.NewClient(ctx, opts...)
if err != nil {
return xerrors.Errorf("connect to agent socket: %w", err)
}
defer client.Close()
ready, err := client.SyncReady(ctx, unitName)
if err != nil {
return xerrors.Errorf("error checking dependencies: %w", err)
}
if !ready {
cliui.Infof(i.Stdout, "Waiting for dependencies of unit '%s' to be satisfied...", unitName)
ticker := time.NewTicker(syncPollInterval)
defer ticker.Stop()
pollLoop:
for {
select {
case <-ctx.Done():
if ctx.Err() == context.DeadlineExceeded {
return xerrors.Errorf("timeout waiting for dependencies of unit '%s'", unitName)
}
return ctx.Err()
case <-ticker.C:
ready, err := client.SyncReady(ctx, unitName)
if err != nil {
return xerrors.Errorf("error checking dependencies: %w", err)
}
if ready {
break pollLoop
}
}
}
}
if err := client.SyncStart(ctx, unitName); err != nil {
return xerrors.Errorf("start unit failed: %w", err)
}
cliui.Info(i.Stdout, "Success")
return nil
},
}
cmd.Options = append(cmd.Options, serpent.Option{
Flag: "timeout",
Description: "Maximum time to wait for dependencies (e.g., 30s, 5m). 5m by default.",
Value: serpent.DurationOf(&timeout),
Default: "5m",
})
return cmd
}
+88
View File
@@ -0,0 +1,88 @@
package cli
import (
"fmt"
"golang.org/x/xerrors"
"github.com/coder/serpent"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/unit"
"github.com/coder/coder/v2/cli/cliui"
)
func (*RootCmd) syncStatus(socketPath *string) *serpent.Command {
formatter := cliui.NewOutputFormatter(
cliui.ChangeFormatterData(
cliui.TableFormat(
[]agentsocket.DependencyInfo{},
[]string{
"depends on",
"required status",
"current status",
"satisfied",
},
),
func(data any) (any, error) {
resp, ok := data.(agentsocket.SyncStatusResponse)
if !ok {
return nil, xerrors.Errorf("expected agentsocket.SyncStatusResponse, got %T", data)
}
return resp.Dependencies, nil
}),
cliui.JSONFormat(),
)
cmd := &serpent.Command{
Use: "status <unit>",
Short: "Show unit status and dependency state",
Long: "Show the current status of a unit, whether it is ready to start, and lists its dependencies. Shows which dependencies are satisfied and which are still pending. Supports multiple output formats.",
Handler: func(i *serpent.Invocation) error {
ctx := i.Context()
if len(i.Args) != 1 {
return xerrors.New("exactly one unit name is required")
}
unit := unit.ID(i.Args[0])
opts := []agentsocket.Option{}
if *socketPath != "" {
opts = append(opts, agentsocket.WithPath(*socketPath))
}
client, err := agentsocket.NewClient(ctx, opts...)
if err != nil {
return xerrors.Errorf("connect to agent socket: %w", err)
}
defer client.Close()
statusResp, err := client.SyncStatus(ctx, unit)
if err != nil {
return xerrors.Errorf("get status failed: %w", err)
}
var out string
header := fmt.Sprintf("Unit: %s\nStatus: %s\nReady: %t\n\nDependencies:\n", unit, statusResp.Status, statusResp.IsReady)
if formatter.FormatID() == "table" && len(statusResp.Dependencies) == 0 {
out = header + "No dependencies found"
} else {
out, err = formatter.Format(ctx, statusResp)
if err != nil {
return xerrors.Errorf("format status: %w", err)
}
if formatter.FormatID() == "table" {
out = header + out
}
}
_, _ = fmt.Fprintln(i.Stdout, out)
return nil
},
}
formatter.AttachOptions(&cmd.Options)
return cmd
}
+330
View File
@@ -0,0 +1,330 @@
//go:build !windows
package cli_test
import (
"bytes"
"context"
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/require"
"cdr.dev/slog"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/testutil"
)
// setupSocketServer creates an agentsocket server at a temporary path for testing.
// Returns the socket path and a cleanup function. The path should be passed to
// sync commands via the --socket-path flag.
func setupSocketServer(t *testing.T) (path string, cleanup func()) {
t.Helper()
// Use a temporary socket path for each test
socketPath := filepath.Join(tempDirUnixSocket(t), "test.sock")
// Create parent directory if needed
parentDir := filepath.Dir(socketPath)
err := os.MkdirAll(parentDir, 0o700)
require.NoError(t, err, "create socket directory")
server, err := agentsocket.NewServer(
slog.Make().Leveled(slog.LevelDebug),
agentsocket.WithPath(socketPath),
)
require.NoError(t, err, "create socket server")
// Return cleanup function
return socketPath, func() {
err := server.Close()
require.NoError(t, err, "close socket server")
_ = os.Remove(socketPath)
}
}
func TestSyncCommands_Golden(t *testing.T) {
t.Parallel()
t.Run("ping", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "ping", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err := inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/ping_success", outBuf.Bytes(), nil)
})
t.Run("start_no_dependencies", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "start", "test-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err := inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/start_no_dependencies", outBuf.Bytes(), nil)
})
t.Run("start_with_dependencies", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
// Set up dependency: test-unit depends on dep-unit
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(path))
require.NoError(t, err)
// Declare dependency
err = client.SyncWant(ctx, "test-unit", "dep-unit")
require.NoError(t, err)
client.Close()
// Start a goroutine to complete the dependency after a short delay
// This simulates the dependency being satisfied while start is waiting
// The delay ensures the "Waiting..." message appears in the output
done := make(chan error, 1)
go func() {
// Wait a moment to let the start command begin waiting and print the message
time.Sleep(100 * time.Millisecond)
compCtx := context.Background()
compClient, err := agentsocket.NewClient(compCtx, agentsocket.WithPath(path))
if err != nil {
done <- err
return
}
defer compClient.Close()
// Start and complete the dependency unit
err = compClient.SyncStart(compCtx, "dep-unit")
if err != nil {
done <- err
return
}
err = compClient.SyncComplete(compCtx, "dep-unit")
done <- err
}()
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "start", "test-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
// Run the start command - it should wait for the dependency
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
// Ensure the completion goroutine finished
select {
case err := <-done:
require.NoError(t, err, "complete dependency")
case <-time.After(time.Second):
// Goroutine should have finished by now
}
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/start_with_dependencies", outBuf.Bytes(), nil)
})
t.Run("want", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "want", "test-unit", "dep-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err := inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/want_success", outBuf.Bytes(), nil)
})
t.Run("complete", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
// First start the unit
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(path))
require.NoError(t, err)
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
client.Close()
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "complete", "test-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/complete_success", outBuf.Bytes(), nil)
})
t.Run("status_pending", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
// Set up a unit with unsatisfied dependency
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(path))
require.NoError(t, err)
err = client.SyncWant(ctx, "test-unit", "dep-unit")
require.NoError(t, err)
client.Close()
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "status", "test-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/status_pending", outBuf.Bytes(), nil)
})
t.Run("status_started", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
// Start a unit
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(path))
require.NoError(t, err)
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
client.Close()
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "status", "test-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/status_started", outBuf.Bytes(), nil)
})
t.Run("status_completed", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
// Start and complete a unit
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(path))
require.NoError(t, err)
err = client.SyncStart(ctx, "test-unit")
require.NoError(t, err)
err = client.SyncComplete(ctx, "test-unit")
require.NoError(t, err)
client.Close()
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "status", "test-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/status_completed", outBuf.Bytes(), nil)
})
t.Run("status_with_dependencies", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
// Set up a unit with dependencies, some satisfied, some not
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(path))
require.NoError(t, err)
err = client.SyncWant(ctx, "test-unit", "dep-1")
require.NoError(t, err)
err = client.SyncWant(ctx, "test-unit", "dep-2")
require.NoError(t, err)
// Complete dep-1, leave dep-2 incomplete
err = client.SyncStart(ctx, "dep-1")
require.NoError(t, err)
err = client.SyncComplete(ctx, "dep-1")
require.NoError(t, err)
client.Close()
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "status", "test-unit", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/status_with_dependencies", outBuf.Bytes(), nil)
})
t.Run("status_json_format", func(t *testing.T) {
t.Parallel()
path, cleanup := setupSocketServer(t)
defer cleanup()
ctx := testutil.Context(t, testutil.WaitShort)
// Set up a unit with dependencies
client, err := agentsocket.NewClient(ctx, agentsocket.WithPath(path))
require.NoError(t, err)
err = client.SyncWant(ctx, "test-unit", "dep-unit")
require.NoError(t, err)
err = client.SyncStart(ctx, "dep-unit")
require.NoError(t, err)
err = client.SyncComplete(ctx, "dep-unit")
require.NoError(t, err)
client.Close()
var outBuf bytes.Buffer
inv, _ := clitest.New(t, "exp", "sync", "status", "test-unit", "--output", "json", "--socket-path", path)
inv.Stdout = &outBuf
inv.Stderr = &outBuf
err = inv.WithContext(ctx).Run()
require.NoError(t, err)
clitest.TestGoldenFile(t, "TestSyncCommands_Golden/status_json_format", outBuf.Bytes(), nil)
})
}
+49
View File
@@ -0,0 +1,49 @@
package cli
import (
"golang.org/x/xerrors"
"github.com/coder/serpent"
"github.com/coder/coder/v2/agent/agentsocket"
"github.com/coder/coder/v2/agent/unit"
"github.com/coder/coder/v2/cli/cliui"
)
func (*RootCmd) syncWant(socketPath *string) *serpent.Command {
cmd := &serpent.Command{
Use: "want <unit> <depends-on>",
Short: "Declare that a unit depends on another unit completing before it can start",
Long: "Declare that a unit depends on another unit completing before it can start. The unit specified first will not start until the second has signaled that it has completed.",
Handler: func(i *serpent.Invocation) error {
ctx := i.Context()
if len(i.Args) != 2 {
return xerrors.New("exactly two arguments are required: unit and depends-on")
}
dependentUnit := unit.ID(i.Args[0])
dependsOn := unit.ID(i.Args[1])
opts := []agentsocket.Option{}
if *socketPath != "" {
opts = append(opts, agentsocket.WithPath(*socketPath))
}
client, err := agentsocket.NewClient(ctx, opts...)
if err != nil {
return xerrors.Errorf("connect to agent socket: %w", err)
}
defer client.Close()
if err := client.SyncWant(ctx, dependentUnit, dependsOn); err != nil {
return xerrors.Errorf("declare dependency failed: %w", err)
}
cliui.Info(i.Stdout, "Success")
return nil
},
}
return cmd
}
+1 -1
View File
@@ -8,7 +8,7 @@ func (r *RootCmd) tasksCommand() *serpent.Command {
cmd := &serpent.Command{
Use: "task",
Aliases: []string{"tasks"},
Short: "Experimental task commands.",
Short: "Manage tasks",
Handler: func(i *serpent.Invocation) error {
return i.Command.HelpHandler(i)
},
@@ -28,27 +28,27 @@ func (r *RootCmd) taskCreate() *serpent.Command {
cmd := &serpent.Command{
Use: "create [input]",
Short: "Create an experimental task",
Short: "Create a task",
Long: FormatExamples(
Example{
Description: "Create a task with direct input",
Command: "coder exp task create \"Add authentication to the user service\"",
Command: "coder task create \"Add authentication to the user service\"",
},
Example{
Description: "Create a task with stdin input",
Command: "echo \"Add authentication to the user service\" | coder exp task create",
Command: "echo \"Add authentication to the user service\" | coder task create",
},
Example{
Description: "Create a task with a specific name",
Command: "coder exp task create --name task1 \"Add authentication to the user service\"",
Command: "coder task create --name task1 \"Add authentication to the user service\"",
},
Example{
Description: "Create a task from a specific template / preset",
Command: "coder exp task create --template backend-dev --preset \"My Preset\" \"Add authentication to the user service\"",
Command: "coder task create --template backend-dev --preset \"My Preset\" \"Add authentication to the user service\"",
},
Example{
Description: "Create a task for another user (requires appropriate permissions)",
Command: "coder exp task create --owner user@example.com \"Add authentication to the user service\"",
Command: "coder task create --owner user@example.com \"Add authentication to the user service\"",
},
),
Middleware: serpent.Chain(
@@ -111,8 +111,7 @@ func (r *RootCmd) taskCreate() *serpent.Command {
}
var (
ctx = inv.Context()
expClient = codersdk.NewExperimentalClient(client)
ctx = inv.Context()
taskInput string
templateVersionID uuid.UUID
@@ -208,7 +207,7 @@ func (r *RootCmd) taskCreate() *serpent.Command {
templateVersionPresetID = preset.ID
}
task, err := expClient.CreateTask(ctx, ownerArg, codersdk.CreateTaskRequest{
task, err := client.CreateTask(ctx, ownerArg, codersdk.CreateTaskRequest{
Name: taskName,
TemplateVersionID: templateVersionID,
TemplateVersionPresetID: templateVersionPresetID,
@@ -69,7 +69,7 @@ func TestTaskCreate(t *testing.T) {
ActiveVersionID: templateVersionID,
},
})
case fmt.Sprintf("/api/experimental/tasks/%s", username):
case fmt.Sprintf("/api/v2/tasks/%s", username):
var req codersdk.CreateTaskRequest
if !httpapi.Read(ctx, w, r, &req) {
return
@@ -329,7 +329,7 @@ func TestTaskCreate(t *testing.T) {
ctx = testutil.Context(t, testutil.WaitShort)
srv = httptest.NewServer(tt.handler(t, ctx))
client = codersdk.New(testutil.MustURL(t, srv.URL))
args = []string{"exp", "task", "create"}
args = []string{"task", "create"}
sb strings.Builder
err error
)
@@ -17,19 +17,19 @@ import (
func (r *RootCmd) taskDelete() *serpent.Command {
cmd := &serpent.Command{
Use: "delete <task> [<task> ...]",
Short: "Delete experimental tasks",
Short: "Delete tasks",
Long: FormatExamples(
Example{
Description: "Delete a single task.",
Command: "$ coder exp task delete task1",
Command: "$ coder task delete task1",
},
Example{
Description: "Delete multiple tasks.",
Command: "$ coder exp task delete task1 task2 task3",
Command: "$ coder task delete task1 task2 task3",
},
Example{
Description: "Delete a task without confirmation.",
Command: "$ coder exp task delete task4 --yes",
Command: "$ coder task delete task4 --yes",
},
),
Middleware: serpent.Chain(
@@ -44,11 +44,10 @@ func (r *RootCmd) taskDelete() *serpent.Command {
if err != nil {
return err
}
exp := codersdk.NewExperimentalClient(client)
var tasks []codersdk.Task
for _, identifier := range inv.Args {
task, err := exp.TaskByIdentifier(ctx, identifier)
task, err := client.TaskByIdentifier(ctx, identifier)
if err != nil {
return xerrors.Errorf("resolve task %q: %w", identifier, err)
}
@@ -71,7 +70,7 @@ func (r *RootCmd) taskDelete() *serpent.Command {
for i, task := range tasks {
display := displayList[i]
if err := exp.DeleteTask(ctx, task.OwnerName, task.ID); err != nil {
if err := client.DeleteTask(ctx, task.OwnerName, task.ID); err != nil {
return xerrors.Errorf("delete task %q: %w", display, err)
}
_, _ = fmt.Fprintln(
@@ -56,7 +56,7 @@ func TestExpTaskDelete(t *testing.T) {
taskID := uuid.MustParse(id1)
return func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/exists":
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/exists":
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK,
codersdk.Task{
@@ -64,7 +64,7 @@ func TestExpTaskDelete(t *testing.T) {
Name: "exists",
OwnerName: "me",
})
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id1:
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id1:
c.deleteCalls.Add(1)
w.WriteHeader(http.StatusAccepted)
default:
@@ -82,13 +82,13 @@ func TestExpTaskDelete(t *testing.T) {
buildHandler: func(c *testCounters) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/"+id2:
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/"+id2:
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse(id2),
OwnerName: "me",
Name: "uuid-task",
})
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id2:
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id2:
c.deleteCalls.Add(1)
w.WriteHeader(http.StatusAccepted)
default:
@@ -104,24 +104,24 @@ func TestExpTaskDelete(t *testing.T) {
buildHandler: func(c *testCounters) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/first":
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/first":
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse(id3),
Name: "first",
OwnerName: "me",
})
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/"+id4:
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/"+id4:
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse(id4),
OwnerName: "me",
Name: "uuid-task-4",
})
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id3:
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id3:
c.deleteCalls.Add(1)
w.WriteHeader(http.StatusAccepted)
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id4:
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/"+id4:
c.deleteCalls.Add(1)
w.WriteHeader(http.StatusAccepted)
default:
@@ -140,7 +140,7 @@ func TestExpTaskDelete(t *testing.T) {
buildHandler: func(_ *testCounters) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks" && r.URL.Query().Get("q") == "owner:\"me\"":
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks" && r.URL.Query().Get("q") == "owner:\"me\"":
httpapi.Write(r.Context(), w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
@@ -163,14 +163,14 @@ func TestExpTaskDelete(t *testing.T) {
taskID := uuid.MustParse(id5)
return func(w http.ResponseWriter, r *http.Request) {
switch {
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/bad":
case r.Method == http.MethodGet && r.URL.Path == "/api/v2/tasks/me/bad":
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
ID: taskID,
Name: "bad",
OwnerName: "me",
})
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/bad":
case r.Method == http.MethodDelete && r.URL.Path == "/api/v2/tasks/me/bad":
httpapi.InternalServerError(w, xerrors.New("boom"))
default:
httpapi.InternalServerError(w, xerrors.New("unwanted path: "+r.Method+" "+r.URL.Path))
@@ -193,7 +193,7 @@ func TestExpTaskDelete(t *testing.T) {
client := codersdk.New(testutil.MustURL(t, srv.URL))
args := append([]string{"exp", "task", "delete"}, tc.args...)
args := append([]string{"task", "delete"}, tc.args...)
inv, root := clitest.New(t, args...)
inv = inv.WithContext(ctx)
clitest.SetupConfig(t, client, root)
+11 -14
View File
@@ -69,27 +69,27 @@ func (r *RootCmd) taskList() *serpent.Command {
cmd := &serpent.Command{
Use: "list",
Short: "List experimental tasks",
Short: "List tasks",
Long: FormatExamples(
Example{
Description: "List tasks for the current user.",
Command: "coder exp task list",
Command: "coder task list",
},
Example{
Description: "List tasks for a specific user.",
Command: "coder exp task list --user someone-else",
Command: "coder task list --user someone-else",
},
Example{
Description: "List all tasks you can view.",
Command: "coder exp task list --all",
Command: "coder task list --all",
},
Example{
Description: "List all your running tasks.",
Command: "coder exp task list --status running",
Command: "coder task list --status running",
},
Example{
Description: "As above, but only show IDs.",
Command: "coder exp task list --status running --quiet",
Command: "coder task list --status running --quiet",
},
),
Aliases: []string{"ls"},
@@ -135,14 +135,13 @@ func (r *RootCmd) taskList() *serpent.Command {
}
ctx := inv.Context()
exp := codersdk.NewExperimentalClient(client)
targetUser := strings.TrimSpace(user)
if targetUser == "" && !all {
targetUser = codersdk.Me
}
tasks, err := exp.Tasks(ctx, &codersdk.TasksFilter{
tasks, err := client.Tasks(ctx, &codersdk.TasksFilter{
Owner: targetUser,
Status: codersdk.TaskStatus(statusFilter),
})
@@ -158,12 +157,6 @@ func (r *RootCmd) taskList() *serpent.Command {
return nil
}
// If no rows and not JSON, show a friendly message.
if len(tasks) == 0 && formatter.FormatID() != cliui.JSONFormat().ID() {
_, _ = fmt.Fprintln(inv.Stderr, "No tasks found.")
return nil
}
rows := make([]taskListRow, len(tasks))
now := time.Now()
for i := range tasks {
@@ -174,6 +167,10 @@ func (r *RootCmd) taskList() *serpent.Command {
if err != nil {
return xerrors.Errorf("format tasks: %w", err)
}
if out == "" {
cliui.Infof(inv.Stderr, "No tasks found.")
return nil
}
_, _ = fmt.Fprintln(inv.Stdout, out)
return nil
},
@@ -69,7 +69,7 @@ func TestExpTaskList(t *testing.T) {
owner := coderdtest.CreateFirstUser(t, client)
memberClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
inv, root := clitest.New(t, "exp", "task", "list")
inv, root := clitest.New(t, "task", "list")
clitest.SetupConfig(t, memberClient, root)
pty := ptytest.New(t).Attach(inv)
@@ -93,7 +93,7 @@ func TestExpTaskList(t *testing.T) {
wantPrompt := "build me a web app"
task := makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStart, wantPrompt)
inv, root := clitest.New(t, "exp", "task", "list", "--column", "id,name,status,initial prompt")
inv, root := clitest.New(t, "task", "list", "--column", "id,name,status,initial prompt")
clitest.SetupConfig(t, memberClient, root)
pty := ptytest.New(t).Attach(inv)
@@ -122,7 +122,7 @@ func TestExpTaskList(t *testing.T) {
pausedTask := makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStop, "stop me please")
// Use JSON output to reliably validate filtering.
inv, root := clitest.New(t, "exp", "task", "list", "--status=paused", "--output=json")
inv, root := clitest.New(t, "task", "list", "--status=paused", "--output=json")
clitest.SetupConfig(t, memberClient, root)
ctx := testutil.Context(t, testutil.WaitShort)
@@ -153,7 +153,7 @@ func TestExpTaskList(t *testing.T) {
_ = makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStart, "other-task")
task := makeAITask(t, db, owner.OrganizationID, owner.UserID, owner.UserID, database.WorkspaceTransitionStart, "me-task")
inv, root := clitest.New(t, "exp", "task", "list", "--user", "me")
inv, root := clitest.New(t, "task", "list", "--user", "me")
//nolint:gocritic // Owner client is intended here smoke test the member task not showing up.
clitest.SetupConfig(t, client, root)
@@ -180,7 +180,7 @@ func TestExpTaskList(t *testing.T) {
task2 := makeAITask(t, db, owner.OrganizationID, owner.UserID, memberUser.ID, database.WorkspaceTransitionStop, "stop me please")
// Given: We add the `--quiet` flag
inv, root := clitest.New(t, "exp", "task", "list", "--quiet")
inv, root := clitest.New(t, "task", "list", "--quiet")
clitest.SetupConfig(t, memberClient, root)
ctx := testutil.Context(t, testutil.WaitShort)
@@ -224,7 +224,7 @@ func TestExpTaskList_OwnerCanListOthers(t *testing.T) {
t.Parallel()
// As the owner, list only member A tasks.
inv, root := clitest.New(t, "exp", "task", "list", "--user", memberAUser.Username, "--output=json")
inv, root := clitest.New(t, "task", "list", "--user", memberAUser.Username, "--output=json")
//nolint:gocritic // Owner client is intended here to allow member tasks to be listed.
clitest.SetupConfig(t, ownerClient, root)
@@ -252,7 +252,7 @@ func TestExpTaskList_OwnerCanListOthers(t *testing.T) {
// As the owner, list all tasks to verify both member tasks are present.
// Use JSON output to reliably validate filtering.
inv, root := clitest.New(t, "exp", "task", "list", "--all", "--output=json")
inv, root := clitest.New(t, "task", "list", "--all", "--output=json")
//nolint:gocritic // Owner client is intended here to allow all tasks to be listed.
clitest.SetupConfig(t, ownerClient, root)
+8 -4
View File
@@ -28,7 +28,7 @@ func (r *RootCmd) taskLogs() *serpent.Command {
Long: FormatExamples(
Example{
Description: "Show logs for a given task.",
Command: "coder exp task logs task1",
Command: "coder task logs task1",
}),
Middleware: serpent.Chain(
serpent.RequireNArgs(1),
@@ -41,16 +41,15 @@ func (r *RootCmd) taskLogs() *serpent.Command {
var (
ctx = inv.Context()
exp = codersdk.NewExperimentalClient(client)
identifier = inv.Args[0]
)
task, err := exp.TaskByIdentifier(ctx, identifier)
task, err := client.TaskByIdentifier(ctx, identifier)
if err != nil {
return xerrors.Errorf("resolve task %q: %w", identifier, err)
}
logs, err := exp.TaskLogs(ctx, codersdk.Me, task.ID)
logs, err := client.TaskLogs(ctx, codersdk.Me, task.ID)
if err != nil {
return xerrors.Errorf("get task logs: %w", err)
}
@@ -60,6 +59,11 @@ func (r *RootCmd) taskLogs() *serpent.Command {
return xerrors.Errorf("format task logs: %w", err)
}
if out == "" {
cliui.Infof(inv.Stderr, "No task logs found.")
return nil
}
_, _ = fmt.Fprintln(inv.Stdout, out)
return nil
},
@@ -46,7 +46,7 @@ func Test_TaskLogs(t *testing.T) {
userClient := client // user already has access to their own workspace
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "logs", task.Name, "--output", "json")
inv, root := clitest.New(t, "task", "logs", task.Name, "--output", "json")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -72,7 +72,7 @@ func Test_TaskLogs(t *testing.T) {
userClient := client
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "logs", task.ID.String(), "--output", "json")
inv, root := clitest.New(t, "task", "logs", task.ID.String(), "--output", "json")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -98,7 +98,7 @@ func Test_TaskLogs(t *testing.T) {
userClient := client
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "logs", task.ID.String())
inv, root := clitest.New(t, "task", "logs", task.ID.String())
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -121,7 +121,7 @@ func Test_TaskLogs(t *testing.T) {
userClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "logs", "doesnotexist")
inv, root := clitest.New(t, "task", "logs", "doesnotexist")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -139,7 +139,7 @@ func Test_TaskLogs(t *testing.T) {
userClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "logs", uuid.Nil.String())
inv, root := clitest.New(t, "task", "logs", uuid.Nil.String())
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -155,7 +155,7 @@ func Test_TaskLogs(t *testing.T) {
client, task := setupCLITaskTest(ctx, t, fakeAgentAPITaskLogsErr(assert.AnError))
userClient := client
inv, root := clitest.New(t, "exp", "task", "logs", task.ID.String())
inv, root := clitest.New(t, "task", "logs", task.ID.String())
clitest.SetupConfig(t, userClient, root)
err := inv.WithContext(ctx).Run()
+4 -5
View File
@@ -17,10 +17,10 @@ func (r *RootCmd) taskSend() *serpent.Command {
Short: "Send input to a task",
Long: FormatExamples(Example{
Description: "Send direct input to a task.",
Command: "coder exp task send task1 \"Please also add unit tests\"",
Command: "coder task send task1 \"Please also add unit tests\"",
}, Example{
Description: "Send input from stdin to a task.",
Command: "echo \"Please also add unit tests\" | coder exp task send task1 --stdin",
Command: "echo \"Please also add unit tests\" | coder task send task1 --stdin",
}),
Middleware: serpent.RequireRangeArgs(1, 2),
Options: serpent.OptionSet{
@@ -39,7 +39,6 @@ func (r *RootCmd) taskSend() *serpent.Command {
var (
ctx = inv.Context()
exp = codersdk.NewExperimentalClient(client)
identifier = inv.Args[0]
taskInput string
@@ -60,12 +59,12 @@ func (r *RootCmd) taskSend() *serpent.Command {
taskInput = inv.Args[1]
}
task, err := exp.TaskByIdentifier(ctx, identifier)
task, err := client.TaskByIdentifier(ctx, identifier)
if err != nil {
return xerrors.Errorf("resolve task: %w", err)
}
if err = exp.TaskSend(ctx, codersdk.Me, task.ID, codersdk.TaskSendRequest{Input: taskInput}); err != nil {
if err = client.TaskSend(ctx, codersdk.Me, task.ID, codersdk.TaskSendRequest{Input: taskInput}); err != nil {
return xerrors.Errorf("send input to task: %w", err)
}
@@ -30,7 +30,7 @@ func Test_TaskSend(t *testing.T) {
userClient := client
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "send", task.Name, "carry on with the task")
inv, root := clitest.New(t, "task", "send", task.Name, "carry on with the task")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -46,7 +46,7 @@ func Test_TaskSend(t *testing.T) {
userClient := client
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "send", task.ID.String(), "carry on with the task")
inv, root := clitest.New(t, "task", "send", task.ID.String(), "carry on with the task")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -62,7 +62,7 @@ func Test_TaskSend(t *testing.T) {
userClient := client
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "send", task.Name, "--stdin")
inv, root := clitest.New(t, "task", "send", task.Name, "--stdin")
inv.Stdout = &stdout
inv.Stdin = strings.NewReader("carry on with the task")
clitest.SetupConfig(t, userClient, root)
@@ -80,7 +80,7 @@ func Test_TaskSend(t *testing.T) {
userClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "send", "doesnotexist", "some task input")
inv, root := clitest.New(t, "task", "send", "doesnotexist", "some task input")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -98,7 +98,7 @@ func Test_TaskSend(t *testing.T) {
userClient, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "send", uuid.Nil.String(), "some task input")
inv, root := clitest.New(t, "task", "send", uuid.Nil.String(), "some task input")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -114,7 +114,7 @@ func Test_TaskSend(t *testing.T) {
userClient, task := setupCLITaskTest(ctx, t, fakeAgentAPITaskSendErr(t, assert.AnError))
var stdout strings.Builder
inv, root := clitest.New(t, "exp", "task", "send", task.Name, "some task input")
inv, root := clitest.New(t, "task", "send", task.Name, "some task input")
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
@@ -47,11 +47,11 @@ func (r *RootCmd) taskStatus() *serpent.Command {
Long: FormatExamples(
Example{
Description: "Show the status of a given task.",
Command: "coder exp task status task1",
Command: "coder task status task1",
},
Example{
Description: "Watch the status of a given task until it completes (idle or stopped).",
Command: "coder exp task status task1 --watch",
Command: "coder task status task1 --watch",
},
),
Use: "status",
@@ -83,10 +83,9 @@ func (r *RootCmd) taskStatus() *serpent.Command {
}
ctx := i.Context()
exp := codersdk.NewExperimentalClient(client)
identifier := i.Args[0]
task, err := exp.TaskByIdentifier(ctx, identifier)
task, err := client.TaskByIdentifier(ctx, identifier)
if err != nil {
return err
}
@@ -107,7 +106,7 @@ func (r *RootCmd) taskStatus() *serpent.Command {
// TODO: implement streaming updates instead of polling
lastStatusRow := tsr
for range t.C {
task, err := exp.TaskByID(ctx, task.ID)
task, err := client.TaskByID(ctx, task.ID)
if err != nil {
return err
}
@@ -36,7 +36,7 @@ func Test_TaskStatus(t *testing.T) {
hf: func(ctx context.Context, _ time.Time) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/experimental/tasks/me/doesnotexist":
case "/api/v2/tasks/me/doesnotexist":
httpapi.ResourceNotFound(w)
return
default:
@@ -52,7 +52,7 @@ func Test_TaskStatus(t *testing.T) {
hf: func(ctx context.Context, now time.Time) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/experimental/tasks/me/exists":
case "/api/v2/tasks/me/exists":
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
WorkspaceStatus: codersdk.WorkspaceStatusRunning,
@@ -88,7 +88,7 @@ func Test_TaskStatus(t *testing.T) {
var calls atomic.Int64
return func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/experimental/tasks/me/exists":
case "/api/v2/tasks/me/exists":
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
@@ -103,7 +103,7 @@ func Test_TaskStatus(t *testing.T) {
Status: codersdk.TaskStatusPending,
})
return
case "/api/experimental/tasks/me/11111111-1111-1111-1111-111111111111":
case "/api/v2/tasks/me/11111111-1111-1111-1111-111111111111":
defer calls.Add(1)
switch calls.Load() {
case 0:
@@ -189,6 +189,7 @@ func Test_TaskStatus(t *testing.T) {
"owner_id": "00000000-0000-0000-0000-000000000000",
"owner_name": "me",
"name": "exists",
"display_name": "Task exists",
"template_id": "00000000-0000-0000-0000-000000000000",
"template_version_id": "00000000-0000-0000-0000-000000000000",
"template_name": "",
@@ -218,11 +219,12 @@ func Test_TaskStatus(t *testing.T) {
ts := time.Date(2025, 8, 26, 12, 34, 56, 0, time.UTC)
return func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/api/experimental/tasks/me/exists":
case "/api/v2/tasks/me/exists":
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
OwnerName: "me",
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
DisplayName: "Task exists",
OwnerName: "me",
WorkspaceAgentHealth: &codersdk.WorkspaceAgentHealth{
Healthy: true,
},
@@ -254,7 +256,7 @@ func Test_TaskStatus(t *testing.T) {
srv = httptest.NewServer(http.HandlerFunc(tc.hf(ctx, now)))
client = codersdk.New(testutil.MustURL(t, srv.URL))
sb = strings.Builder{}
args = []string{"exp", "task", "status", "--watch-interval", testutil.IntervalFast.String()}
args = []string{"task", "status", "--watch-interval", testutil.IntervalFast.String()}
)
t.Cleanup(srv.Close)
+8 -10
View File
@@ -60,14 +60,14 @@ func Test_Tasks(t *testing.T) {
}{
{
name: "create task",
cmdArgs: []string{"exp", "task", "create", "test task input for " + t.Name(), "--name", taskName, "--template", taskTpl.Name},
cmdArgs: []string{"task", "create", "test task input for " + t.Name(), "--name", taskName, "--template", taskTpl.Name},
assertFn: func(stdout string, userClient *codersdk.Client) {
require.Contains(t, stdout, taskName, "task name should be in output")
},
},
{
name: "list tasks after create",
cmdArgs: []string{"exp", "task", "list", "--output", "json"},
cmdArgs: []string{"task", "list", "--output", "json"},
assertFn: func(stdout string, userClient *codersdk.Client) {
var tasks []codersdk.Task
err := json.NewDecoder(strings.NewReader(stdout)).Decode(&tasks)
@@ -88,7 +88,7 @@ func Test_Tasks(t *testing.T) {
},
{
name: "get task status after create",
cmdArgs: []string{"exp", "task", "status", taskName, "--output", "json"},
cmdArgs: []string{"task", "status", taskName, "--output", "json"},
assertFn: func(stdout string, userClient *codersdk.Client) {
var task codersdk.Task
require.NoError(t, json.NewDecoder(strings.NewReader(stdout)).Decode(&task), "should unmarshal task status")
@@ -98,12 +98,12 @@ func Test_Tasks(t *testing.T) {
},
{
name: "send task message",
cmdArgs: []string{"exp", "task", "send", taskName, "hello"},
cmdArgs: []string{"task", "send", taskName, "hello"},
// Assertions for this happen in the fake agent API handler.
},
{
name: "read task logs",
cmdArgs: []string{"exp", "task", "logs", taskName, "--output", "json"},
cmdArgs: []string{"task", "logs", taskName, "--output", "json"},
assertFn: func(stdout string, userClient *codersdk.Client) {
var logs []codersdk.TaskLogEntry
require.NoError(t, json.NewDecoder(strings.NewReader(stdout)).Decode(&logs), "should unmarshal task logs")
@@ -118,12 +118,11 @@ func Test_Tasks(t *testing.T) {
},
{
name: "delete task",
cmdArgs: []string{"exp", "task", "delete", taskName, "--yes"},
cmdArgs: []string{"task", "delete", taskName, "--yes"},
assertFn: func(stdout string, userClient *codersdk.Client) {
// The task should eventually no longer show up in the list of tasks
testutil.Eventually(ctx, t, func(ctx context.Context) bool {
expClient := codersdk.NewExperimentalClient(userClient)
tasks, err := expClient.Tasks(ctx, &codersdk.TasksFilter{})
tasks, err := userClient.Tasks(ctx, &codersdk.TasksFilter{})
if !assert.NoError(t, err) {
return false
}
@@ -248,8 +247,7 @@ func setupCLITaskTest(ctx context.Context, t *testing.T, agentAPIHandlers map[st
template := createAITaskTemplate(t, client, owner.OrganizationID, withSidebarURL(fakeAPI.URL()), withAgentToken(authToken))
wantPrompt := "test prompt"
exp := codersdk.NewExperimentalClient(userClient)
task, err := exp.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
task, err := userClient.CreateTask(ctx, codersdk.Me, codersdk.CreateTaskRequest{
TemplateVersionID: template.ActiveVersionID,
Input: wantPrompt,
Name: "test-task",
+6 -6
View File
@@ -30,18 +30,18 @@ func (r *RootCmd) templateList() *serpent.Command {
return err
}
if len(templates) == 0 {
_, _ = fmt.Fprintf(inv.Stderr, "%s No templates found! Create one:\n\n", Caret)
_, _ = fmt.Fprintln(inv.Stderr, color.HiMagentaString(" $ coder templates push <directory>\n"))
return nil
}
rows := templatesToRows(templates...)
out, err := formatter.Format(inv.Context(), rows)
if err != nil {
return err
}
if out == "" {
_, _ = fmt.Fprintf(inv.Stderr, "%s No templates found! Create one:\n\n", Caret)
_, _ = fmt.Fprintln(inv.Stderr, color.HiMagentaString(" $ coder templates push <directory>\n"))
return nil
}
_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
+7 -2
View File
@@ -106,7 +106,7 @@ func (r *RootCmd) templatePresetsList() *serpent.Command {
if len(presets) == 0 {
cliui.Infof(
inv.Stdout,
"No presets found for template %q and template-version %q.\n", template.Name, version.Name,
"No presets found for template %q and template-version %q.", template.Name, version.Name,
)
return nil
}
@@ -115,7 +115,7 @@ func (r *RootCmd) templatePresetsList() *serpent.Command {
if formatter.FormatID() == "table" {
cliui.Infof(
inv.Stdout,
"Showing presets for template %q and template version %q.\n", template.Name, version.Name,
"Showing presets for template %q and template version %q.", template.Name, version.Name,
)
}
rows := templatePresetsToRows(presets...)
@@ -124,6 +124,11 @@ func (r *RootCmd) templatePresetsList() *serpent.Command {
return xerrors.Errorf("render table: %w", err)
}
if out == "" {
cliui.Infof(inv.Stderr, "No template presets found.")
return nil
}
_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
+5
View File
@@ -121,6 +121,11 @@ func (r *RootCmd) templateVersionsList() *serpent.Command {
return xerrors.Errorf("render table: %w", err)
}
if out == "" {
cliui.Infof(inv.Stderr, "No template versions found.")
return nil
}
_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
@@ -0,0 +1 @@
Success
@@ -0,0 +1 @@
Success
@@ -0,0 +1 @@
Success
@@ -0,0 +1,2 @@
Waiting for dependencies of unit 'test-unit' to be satisfied...
Success
@@ -0,0 +1,6 @@
Unit: test-unit
Status: completed
Ready: true
Dependencies:
No dependencies found
@@ -0,0 +1,13 @@
{
"unit_name": "test-unit",
"status": "pending",
"is_ready": true,
"dependencies": [
{
"depends_on": "dep-unit",
"required_status": "completed",
"current_status": "completed",
"is_satisfied": true
}
]
}
@@ -0,0 +1,7 @@
Unit: test-unit
Status: pending
Ready: false
Dependencies:
DEPENDS ON REQUIRED STATUS CURRENT STATUS SATISFIED
dep-unit completed not registered false
@@ -0,0 +1,6 @@
Unit: test-unit
Status: started
Ready: true
Dependencies:
No dependencies found

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