Compare commits

...

189 Commits

Author SHA1 Message Date
Spike Curtis fb08b94694 chore: mock codersdk in show command 2025-11-21 09:25:34 +00:00
Jaayden Halko ddcc841bdc fix: set a default for presets to match the app default (#20848) 2025-11-20 10:55:07 -08:00
Marcin Tojek d004710a74 feat: add prebuild invalidation via last_invalidated_at timestamp (#20582)
Updates #17917
2025-11-20 17:12:25 +01:00
Jaayden Halko c2319e5b4e fix: prevent tooltip appearing on dropdown open (#20765)
The tooltip inside CopyButton inside Userdropdown is appearing
automatically when the dropdown is opened. This feels a bit janky and
the goal of this fix is to only show the tooltip content when the user
hovers the copy button.



https://github.com/user-attachments/assets/2e41da8d-08c5-476b-b0fc-a40d4f8e3d6c
2025-11-20 08:38:07 -05:00
Phorcys 0cd33d1abb chore(docs/admin/users): fix typo in headless auth page (#20841) 2025-11-20 11:25:54 +01:00
Phorcys 426cc98f7c fix(site/src/modules/apps): distinguish JB Toolbox from Gateway (#20830)
Edits the "To use <APP>, you need to have Jetbrains Toolbox installed"
error message to vary based on JetBrains Toolbox vs. Gateway.

---------

Co-authored-by: Jake Howell <jake@hwll.me>
2025-11-20 09:54:42 +00:00
Spike Curtis 007f2df079 fix: use API, not request context to insert audit/connection logs (#20829)
Fixes: #20744

Upsert audit and connection log entries with a context derived from the API context, rather than the individual request so that we don't error out if the request is canceled or the client hangs up (e.g. if we return an error).
2025-11-20 13:01:50 +04:00
blinkagent[bot] 48b8e22502 fix: add Windows stub for CacheTFProviders (#20840)
Fixes https://github.com/coder/internal/issues/1119

## Description

The `CacheTFProviders` function in `testutil/terraform_cache.go` was
only available on Linux and macOS due to the `//go:build linux ||
darwin` build tag. This caused a compile error on Windows when
`enterprise/coderd/workspaces_test.go` tried to call it:

```
enterprise\coderd\workspaces_test.go:3403:28: undefined: testutil.CacheTFProviders
```

## Changes

1. Added `testutil/terraform_cache_windows.go` with a Windows-specific
stub implementation that returns an empty string
2. Updated `downloadProviders` helper in
`enterprise/coderd/workspaces_test.go` to handle empty paths gracefully

## Behavior

- On Linux/macOS: Terraform providers are cached as before
- On Windows: Provider caching is skipped, tests download providers
normally during `terraform init`

## Testing

This should fix the Windows nightly gauntlet failure. The test will
still run on Windows, just without provider caching optimization.

Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
2025-11-20 07:52:07 +00:00
dependabot[bot] 18bef5ea2f chore: bump golang.org/x/crypto from 0.44.0 to 0.45.0 (#20838)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from
0.44.0 to 0.45.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/crypto/commit/4e0068c0098be10d7025c99ab7c50ce454c1f0f9"><code>4e0068c</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/crypto/commit/e79546e28b85ea53dd37afe1c4102746ef553b9c"><code>e79546e</code></a>
ssh: curb GSSAPI DoS risk by limiting number of specified OIDs</li>
<li><a
href="https://github.com/golang/crypto/commit/f91f7a7c31bf90b39c1de895ad116a2bacc88748"><code>f91f7a7</code></a>
ssh/agent: prevent panic on malformed constraint</li>
<li><a
href="https://github.com/golang/crypto/commit/2df4153a0311bdfea44376e0eb6ef2faefb0275b"><code>2df4153</code></a>
acme/autocert: let automatic renewal work with short lifetime certs</li>
<li><a
href="https://github.com/golang/crypto/commit/bcf6a849efcf4702fa5172cb0998b46c3da1e989"><code>bcf6a84</code></a>
acme: pass context to request</li>
<li><a
href="https://github.com/golang/crypto/commit/b4f2b62076abeee4e43fb59544dac565715fbf1e"><code>b4f2b62</code></a>
ssh: fix error message on unsupported cipher</li>
<li><a
href="https://github.com/golang/crypto/commit/79ec3a51fcc7fbd2691d56155d578225ccc542e2"><code>79ec3a5</code></a>
ssh: allow to bind to a hostname in remote forwarding</li>
<li>See full diff in <a
href="https://github.com/golang/crypto/compare/v0.44.0...v0.45.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=golang.org/x/crypto&package-manager=go_modules&previous-version=0.44.0&new-version=0.45.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)
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-11-20 00:41:43 +00:00
Asher b4cb490c72 chore: enable debug logs over playwright (#20784) 2025-11-19 15:27:40 -09:00
DevCats 7615c2792b chore: add positron icon (#20780)
Co-authored-by: ケイラ <mckayla@hey.com>
2025-11-19 16:19:54 -06:00
Susana Ferreira 753e125758 chore(site): add storybook stories for task initialization states (#20760)
Adds a Storybook story to visualize the task initialization states
(workspace pending/starting, agent connecting/starting) that were
recently added.

<img width="2310" height="1600" alt="Screenshot 2025-11-17 at 18 58 55"
src="https://github.com/user-attachments/assets/16471dcf-2f7d-41d2-beba-2cf0c84c9bf0"
/>

Follow-up from PR: https://github.com/coder/coder/pull/20692
2025-11-19 18:30:14 +00:00
Susana Ferreira 17edeeaf04 fix(site): fix flaky Chromatic tests (#20808)
## Problem

The `OrgsSortedAlphabetically` test from
`OrganizationSidebarView.stories.tsx` was failing on Chromatic. Test
logic was attempting to verify organization sorting order
programmatically. This was identified in the Chromatic build of PR:
https://www.chromatic.com/build?appId=624de63c6aacee003aa84340&number=26015

After fixing this test, two additional tests started failing:
* `VanillaJavascriptError ` from `GlobalErrorBoundary.stories.tsx`: Test
was making incorrect assertions about stack trace content
* `MarkAllNotificationsAsReadError` from
`NotificationsInbox.stories.tsx`: Test was flaky due to competing
WebSocket error messages

## Solution

These are Chromatic snapshot tests, so implementation details (like
sorting order or exact error message content) are already validated by
the visual snapshots. Programmatic assertions were causing flakiness and
are redundant.
2025-11-19 18:17:12 +00:00
Sas Swart 500c17e257 feat(agent): add agent unit manager (#20715)
relates to: https://github.com/coder/internal/issues/1094

This is number 1 of 5 pull requests in an effort to add agent script
ordering. It adds a unit manager, which uses an underlying DAG and a
list of subscribers to inform units when their dependencies have changed
in status.

In follow-up PRs:
* This unit manager will be plumbed into the workspace agent struct. 
* It will then be exposed to users via a new socket based drpc API 
* The agentsocket API will then become accessible via CLI commands that
allow coder scripts to express their dependencies on one another.

This is an experimental feature. There may be ways to improve the
efficiency of the manager struct, but it is more important to validate
this feature with customers before we invest in such optimizations.

See the tests for examples of how units may communicate with one
another. Actual CLI usage will be analogous.

I used an LLM to produce some of these changes, but I have conducted
thorough self review and consider this contribution to be ready for an
external reviewer.
2025-11-19 19:03:37 +02:00
Cian Johnston 35b9df86b3 chore(docs): document preset description and icon fields (#20705)
Closes https://github.com/coder/coder/issues/20599

Generated by Claude Code, reviewed by me.
2025-11-19 10:02:43 -06:00
Steven Masley aff208048e feat: fix build timeline to include entire stage timings (#20805)
Measure entire stage durations for each terraform cmd execution
2025-11-19 09:35:33 -06:00
Steven Masley a10c5ff381 chore: protect build timings insert for invalid enums (#20821)
Database insert errors will fail the transaction. So this error is
fatal. Properly return it for a better error call stack, and not just
hiding the error in the logs.
2025-11-19 09:34:19 -06:00
Mathias Fredriksson f6556fce9f test(coderd/workspaceapps/apptest): fix lastusedat assertion for all test (#20827)
The test flake can be verified by setting `ReportInterval` to a really
low value, like `100 * time.Millisecond`.

We now set it to a really high value to avoid triggering flush without 
manually calling the function in test. This can easily happen because 
the default value is 30s and we run tests in parallel. The assertion
typically happens such that:

	[use workspace] -> [fetch previous last used] -> [flush]
	-> [fetch new last used]

When this edge case is triggered:

	[use workspace] -> [report interval flush]
	-> [fetch previous last used] -> [flush] -> [fetch new last used]

In this case, both the previous and new last used will be the same,
breaking the test assertion.

Fixes coder/internal#960
Fixes coder/internal#975
2025-11-19 15:10:59 +02:00
Danielle Maywood 8e22cd707a feat(site): add startup script error alerts to Task Page (#20820)
Refactors Task page UI to show startup script errors as compact warning
buttons in the topbar.

Closes https://github.com/coder/coder/issues/20418
2025-11-19 11:44:22 +00:00
Spike Curtis 8ee6e9457e fix: wait for build in task status load generator (#20800)
Wait for the External workspace build job to complete before attempting to pull its credentials from Coder. This resolves a race in the load generator.
2025-11-19 10:35:31 +04:00
Spike Curtis 0bbb7dd0a3 feat: add cleanup to task-status load test runner (#20799)
Implement Cleanup in the task status Runner, to delete the external workspaces created.
2025-11-19 10:24:30 +04:00
Spike Curtis 5ea1353d46 feat: add exp scaletest task-status command (#20761)
Adds `coder exp scaletest task-status` subcommand to generate task status update load on the Coder server.
2025-11-19 10:13:32 +04:00
Jake Howell 52f8143ad3 fix: rename AI Governance to AI Bridge (#20790)
This pull-request simply renames our `AI Governance` feature to `AI
Bridge` whilst we evaluate the future of how we want to render the
governance of AI related features.
2025-11-19 16:47:06 +11:00
AlexanderSarson 085370ec6d chore: add "positron:" to allowed external app protocols (#20803)
<!--

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-19 14:11:56 +11:00
Ethan c12bba40ad fix(enterprise/cli): preserve actual error when getting provisioner key details (#20813)
Fixes #20781

Previously, when `GetProvisionerKey()` failed, the actual error was
swallowed:
```
error: unable to get provisioner key details
```

Now the actual error is preserved using error wrapping, so users can see
the real cause (e.g., 404 Not Found, connection refused, invalid key,
etc.):
```
error: unable to get provisioner key details: GET https://...: 404 Not Found
```

This makes it much easier to diagnose configuration issues.

---
*Generated by [mux](https://cmux.io)*
2025-11-19 02:09:16 +11:00
Paweł Banaszewski 158243d146 fix: add cache for terraform installer files (#20776)
Replaces not working mocks by simple proxy that caches terraform files using test
cache
https://github.com/coder/coder/blob/16b8e6072fd84f45404e3f84bb2b6fea2424b090/testutil/cache.go#L13
Fixes: https://github.com/coder/internal/issues/1126
2025-11-18 09:52:44 +01:00
Yevhenii Shcherbina eb644732d7 feat: enable boundary on dogfood (#20766)
Enable boundary on dogfood.
Allowed domains are specified in config.yaml file.
2025-11-17 16:59:24 -05:00
Yevhenii Shcherbina a83328c1f0 docs: improve boundary docs (#20806)
Update docs for boundary v0.2.0 release.
2025-11-17 15:41:59 -05:00
Steven Masley a2728439ff docs: add API key scopes documentation (#20742)
## Description

Adds a brief section to the API & Session Tokens documentation
explaining API key scopes.

## Changes

- Added "API Key Scopes" section to
`docs/admin/users/sessions-tokens.md`
- Includes overview of scope functionality and security benefits
- Documents scope format (`resource:action`) and wildcard usage
- Provides CLI examples for creating scoped tokens
- Lists common scope examples with descriptions

## Motivation

Users need documentation on how to create and use scoped API tokens for
improved security by limiting token permissions to only necessary
operations.

## Testing

- Reviewed documentation formatting
- Verified markdown structure
- Confirmed examples are accurate
2025-11-17 11:34:01 -06:00
Susana Ferreira 16b8e6072f fix: set codersdk.Task current_state during task initialization (#20692)
## Problem

With the new tasks data model, a task starts with an `initializing`
status. However, the API returns `current_state: null` to represent the
agent state, causing the frontend to display "No message available".
This PR updates `codersdk.Task` to return a `current_state` when the
task is initializing with meaningful messages about what's happening
during task initialization.

**Previous message**

<img width="2764" height="288" alt="Screenshot 2025-11-07 at 09 06 13"
src="https://github.com/user-attachments/assets/feec9f15-91ca-4378-8565-5f9de062d11a"
/>

**New message**

<img width="2726" height="226" alt="Screenshot 2025-11-12 at 11 00 15"
src="https://github.com/user-attachments/assets/2f9bee3e-7ac4-4382-b1c3-1d06bbc2906e"
/>

## Changes

- Populate `current_state` with descriptive initialization messages when
task status is `initializing` and no valid app status exists for the
current build
- **dbfake**: Fix `WorkspaceBuild` builder to properly handle
pending/running jobs by linking tasks without requiring agent/app
resources

**Note:** UI Storybook changes to reflect these new messages will be
addressed in a follow-up PR.

Closes: https://github.com/coder/internal/issues/1063
2025-11-17 13:24:12 +00:00
dependabot[bot] 355150072b chore: bump ubuntu from 0950623 to 104ae83 in /dogfood/coder (#20797)
Bumps ubuntu from `0950623` to `104ae83`.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ubuntu&package-manager=docker&previous-version=jammy&new-version=jammy)](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-17 12:23:50 +00:00
dependabot[bot] ad3e8885e4 chore: bump rust from d9ba801 to cef0ec9 in /dogfood/coder (#20798)
Bumps rust from `d9ba801` to `cef0ec9`.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rust&package-manager=docker&previous-version=slim&new-version=slim)](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-17 12:23:46 +00:00
dependabot[bot] 0b0813e30c ci: bump the github-actions group with 3 updates (#20796)
Bumps the github-actions group with 3 updates:
[crate-ci/typos](https://github.com/crate-ci/typos),
[peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch)
and [github/codeql-action](https://github.com/github/codeql-action).

Updates `crate-ci/typos` from 1.39.0 to 1.39.2
<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.39.2</h2>
<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>v1.39.1</h2>
<h2>[1.39.1] - 2025-11-12</h2>
<h3>Features</h3>
<ul>
<li>Make <code>--help</code> more vibrant</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.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>
<ul>
<li>Don't correct <code>typ</code></li>
<li>Consistently error on unused config fields</li>
</ul>
<h2>[1.37.3] - 2025-10-06</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crate-ci/typos/commit/626c4bedb751ce0b7f03262ca97ddda9a076ae1c"><code>626c4be</code></a>
chore: Release</li>
<li><a
href="https://github.com/crate-ci/typos/commit/c6b458db05d00c3037bc9a1102b84febc9fff2f4"><code>c6b458d</code></a>
docs: Update changelog</li>
<li><a
href="https://github.com/crate-ci/typos/commit/eed04198a67af7f32b16141261aa8f911cba1f5f"><code>eed0419</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1423">#1423</a>
from epage/entrys</li>
<li><a
href="https://github.com/crate-ci/typos/commit/40383f41a2f90743ef28b8c8b1c2d5a42b7651a0"><code>40383f4</code></a>
fix(dict): Don't offer 'entry' as a correction for 'entrys'</li>
<li><a
href="https://github.com/crate-ci/typos/commit/1af53e3774f068183ffd0c7193eb061a2b65a531"><code>1af53e3</code></a>
chore: Release</li>
<li><a
href="https://github.com/crate-ci/typos/commit/e5d291b81a9bd645c218da268c94df78b6e5e605"><code>e5d291b</code></a>
docs: Update changelog</li>
<li><a
href="https://github.com/crate-ci/typos/commit/55474f5ff9f9a923f4e1a218c9b39271517d847e"><code>55474f5</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1417">#1417</a>
from starsep/colorful_help</li>
<li><a
href="https://github.com/crate-ci/typos/commit/78b93759507833a789853c44a1d9a767fcd15024"><code>78b9375</code></a>
feat: Enable colors for typos --help</li>
<li><a
href="https://github.com/crate-ci/typos/commit/308f8f5788c91e7d099279f046cdbc3662956dcd"><code>308f8f5</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1409">#1409</a>
from crate-ci/renovate/actions-download-artifact-6.x</li>
<li><a
href="https://github.com/crate-ci/typos/commit/cf03418f507191943e33099ce6ba74c4c79b0257"><code>cf03418</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1410">#1410</a>
from crate-ci/renovate/actions-setup-python-6.x</li>
<li>Additional commits viewable in <a
href="https://github.com/crate-ci/typos/compare/07d900b8fa1097806b8adb6391b0d3e0ac2fdea7...626c4bedb751ce0b7f03262ca97ddda9a076ae1c">compare
view</a></li>
</ul>
</details>
<br />

Updates `peter-evans/repository-dispatch` from 4.0.0 to 4.0.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/repository-dispatch/releases">peter-evans/repository-dispatch's
releases</a>.</em></p>
<blockquote>
<h2>v4.0.1</h2>
<h2>What's Changed</h2>
<ul>
<li>build(deps): bump peter-evans/repository-dispatch from 3 to 4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/428">peter-evans/repository-dispatch#428</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.127 to
18.19.129 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/429">peter-evans/repository-dispatch#429</a></li>
<li>build(deps): bump the github-actions group with 3 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/431">peter-evans/repository-dispatch#431</a></li>
<li>build(deps-dev): bump <code>@​types/node</code> from 18.19.129 to
18.19.130 in the npm group by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/432">peter-evans/repository-dispatch#432</a></li>
<li>Fix node version in actions.yml by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/repository-dispatch/pull/433">peter-evans/repository-dispatch#433</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/repository-dispatch/compare/v4.0.0...v4.0.1">https://github.com/peter-evans/repository-dispatch/compare/v4.0.0...v4.0.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/28959ce8df70de7be546dd1250a005dd32156697"><code>28959ce</code></a>
Fix node version in actions.yml (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/433">#433</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/25d29c2bbf9b1fd1e3e924e485d754498fdc84fd"><code>25d29c2</code></a>
build(deps-dev): bump <code>@​types/node</code> in the npm group (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/432">#432</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/830136c66487b256600fec7788578990092647bc"><code>830136c</code></a>
build(deps): bump the github-actions group with 3 updates (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/431">#431</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/2c856c63feddee6147cab2f38801935b6a59a765"><code>2c856c6</code></a>
ci: update dependabot config</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/66739071c2122a05106fc2a2c306fdaf33bb9cda"><code>6673907</code></a>
build(deps-dev): bump <code>@​types/node</code> from 18.19.127 to
18.19.129 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/429">#429</a>)</li>
<li><a
href="https://github.com/peter-evans/repository-dispatch/commit/952a211c1efd1abc91cf289f80655b4692ba8cff"><code>952a211</code></a>
build(deps): bump peter-evans/repository-dispatch from 3 to 4 (<a
href="https://redirect.github.com/peter-evans/repository-dispatch/issues/428">#428</a>)</li>
<li>See full diff in <a
href="https://github.com/peter-evans/repository-dispatch/compare/5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f...28959ce8df70de7be546dd1250a005dd32156697">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action` from 4.31.2 to 4.31.3
<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.3</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.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>
<p>See the full <a
href="https://github.com/github/codeql-action/blob/v4.31.3/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.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>
<h2>3.30.6 - 02 Oct 2025</h2>
<ul>
<li>Update default CodeQL bundle version to 2.23.2. <a
href="https://redirect.github.com/github/codeql-action/pull/3168">#3168</a></li>
</ul>
<h2>3.30.5 - 26 Sep 2025</h2>
<ul>
<li>We fixed a bug that was introduced in <code>3.30.4</code> with
<code>upload-sarif</code> which resulted in files without a
<code>.sarif</code> extension not getting uploaded. <a
href="https://redirect.github.com/github/codeql-action/pull/3160">#3160</a></li>
</ul>
<h2>3.30.4 - 25 Sep 2025</h2>
<ul>
<li>We have improved the CodeQL Action's ability to validate that the
workflow it is used in does not use different versions of the CodeQL
Action for different workflow steps. Mixing different versions of the
CodeQL Action in the same workflow is unsupported and can lead to
unpredictable results. A warning will now be emitted from the
<code>codeql-action/init</code> step if different versions of the CodeQL
Action are detected in the workflow file. Additionally, an error will
now be thrown by the other CodeQL Action steps if they load a
configuration file that was generated by a different version of the
<code>codeql-action/init</code> step. <a
href="https://redirect.github.com/github/codeql-action/pull/3099">#3099</a>
and <a
href="https://redirect.github.com/github/codeql-action/pull/3100">#3100</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/014f16e7ab1402f30e7c3329d33797e7948572db"><code>014f16e</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3293">#3293</a>
from github/update-v4.31.3-8c10e89c7</li>
<li><a
href="https://github.com/github/codeql-action/commit/14d898ef09787f3258d7542ed62ad3da38295b68"><code>14d898e</code></a>
Update changelog for v4.31.3</li>
<li><a
href="https://github.com/github/codeql-action/commit/8c10e89c78c754f211c440ce6999ed8668811c3b"><code>8c10e89</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3288">#3288</a>
from github/update-bundle/codeql-bundle-v2.23.5</li>
<li><a
href="https://github.com/github/codeql-action/commit/9777b01a4952c6266ad795197c2dd702065a6d19"><code>9777b01</code></a>
Merge branch 'main' into update-bundle/codeql-bundle-v2.23.5</li>
<li><a
href="https://github.com/github/codeql-action/commit/456a74a6faf33b08baa780e0bf31b41fabd1ca35"><code>456a74a</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3289">#3289</a>
from github/mbg/ci/setup-dotnet</li>
<li><a
href="https://github.com/github/codeql-action/commit/3fac49c14012959fab197865a1813bffe8a04dd1"><code>3fac49c</code></a>
Update remaining workflows</li>
<li><a
href="https://github.com/github/codeql-action/commit/38a3a7258f252b705a070bd91df7a72a50d61318"><code>38a3a72</code></a>
Enable <code>installDotNet</code> in all workflows that analyse C#</li>
<li><a
href="https://github.com/github/codeql-action/commit/58c9eb6c034b7054387301aa21926d94da049b69"><code>58c9eb6</code></a>
Add <code>global.json</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/f20e02164a8bd2f32913932752d67ee2bbf22246"><code>f20e021</code></a>
Add support for adding <code>setup-dotnet</code> steps to
<code>sync.sh</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/8d3d4001e38901ebbee39c134163b67198c956f7"><code>8d3d400</code></a>
Add changelog note</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/0499de31b99561a6d14a36a5f662c2a54f91beee...014f16e7ab1402f30e7c3329d33797e7948572db">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-11-17 12:19:23 +00:00
dependabot[bot] 430c8c2dd2 chore: bump github.com/anthropics/anthropic-sdk-go from 1.17.0 to 1.18.0 (#20795)
Bumps
[github.com/anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go)
from 1.17.0 to 1.18.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.18.0</h2>
<h2>1.18.0 (2025-11-14)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.17.0...v1.18.0">v1.17.0...v1.18.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add support for structured outputs beta (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/fb9cfb4e4b571d5fec7da9874610aa8820aee80c">fb9cfb4</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li>bump gjson version (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/69b5e0e40757884bece66397fb6ca769f4e00118">69b5e0e</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.18.0 (2025-11-14)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.17.0...v1.18.0">v1.17.0...v1.18.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add support for structured outputs beta (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/fb9cfb4e4b571d5fec7da9874610aa8820aee80c">fb9cfb4</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li>bump gjson version (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/69b5e0e40757884bece66397fb6ca769f4e00118">69b5e0e</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/f4266c4d6cb52f0efd239777f322db2387168334"><code>f4266c4</code></a>
release: 1.18.0</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/e3776089b6095d27726c31d82a8e2c9f12bd0cf1"><code>e377608</code></a>
feat(api): add support for structured outputs beta</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/fc01187b262243230c5f5a89c08d835d65b17c6d"><code>fc01187</code></a>
codegen metadata</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/4e9c5a8a928a43e81a133a18ef0396907d833c6a"><code>4e9c5a8</code></a>
codegen metadata</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.17.0...v1.18.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.17.0&new-version=1.18.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-17 12:15:11 +00:00
dependabot[bot] 1c15534c98 chore: bump the x group with 6 updates (#20792)
[//]: # (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 the x group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [golang.org/x/crypto](https://github.com/golang/crypto) | `0.43.0` |
`0.44.0` |
| [golang.org/x/mod](https://github.com/golang/mod) | `0.29.0` |
`0.30.0` |
| [golang.org/x/net](https://github.com/golang/net) | `0.46.0` |
`0.47.0` |
| [golang.org/x/term](https://github.com/golang/term) | `0.36.0` |
`0.37.0` |
| [golang.org/x/text](https://github.com/golang/text) | `0.30.0` |
`0.31.0` |
| [golang.org/x/tools](https://github.com/golang/tools) | `0.38.0` |
`0.39.0` |

Updates `golang.org/x/crypto` from 0.43.0 to 0.44.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/crypto/commit/122a78f140d9d3303ed3261bc374bbbca149140f"><code>122a78f</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/crypto/commit/c0531f9c34514ad5c5551e2d6ce569ca673a8afd"><code>c0531f9</code></a>
all: eliminate vet diagnostics</li>
<li><a
href="https://github.com/golang/crypto/commit/0997000b45e3a40598272081bcad03ffd21b8adb"><code>0997000</code></a>
all: fix some comments</li>
<li><a
href="https://github.com/golang/crypto/commit/017a1aaa2d993492ef6f74ebe7c87f33d82d3717"><code>017a1aa</code></a>
chacha20poly1305: panic on dst and additionalData overlap</li>
<li><a
href="https://github.com/golang/crypto/commit/cf29fa96f8b66328e59829f064539321159bfa5b"><code>cf29fa9</code></a>
sha3: make it mostly a wrapper around crypto/sha3</li>
<li><a
href="https://github.com/golang/crypto/commit/0b7aa0cfb07b6b13ead990b67cb3cb8639871f90"><code>0b7aa0c</code></a>
ssh: use reflect.TypeFor instead of reflect.TypeOf</li>
<li><a
href="https://github.com/golang/crypto/commit/1faea2975ced2153e5086c1ee135f983db10150a"><code>1faea29</code></a>
all: fix some typos in comment</li>
<li>See full diff in <a
href="https://github.com/golang/crypto/compare/v0.43.0...v0.44.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/mod` from 0.29.0 to 0.30.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/mod/commit/7416265ac6eca137286fb2adcc87f9feec458b4c"><code>7416265</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/mod/commit/5517a715a62aaf2d2ab02e64ce67586c60767e8f"><code>5517a71</code></a>
all: fix some comments</li>
<li><a
href="https://github.com/golang/mod/commit/b6cdd1a97c6a688a6a842cdc667ec2e68174ba9d"><code>b6cdd1a</code></a>
modfile: use reflect.TypeFor instead of reflect.TypeOf</li>
<li>See full diff in <a
href="https://github.com/golang/mod/compare/v0.29.0...v0.30.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/net` from 0.46.0 to 0.47.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/net/commit/9a296438e54dff851a45667aa645a97003b44db5"><code>9a29643</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/net/commit/07cefd8a6bb170785052142a96034f2b2f7115bc"><code>07cefd8</code></a>
context: deprecate</li>
<li><a
href="https://github.com/golang/net/commit/5ac9daca088ab4f378d7df849f6c7d28bea86071"><code>5ac9dac</code></a>
publicsuffix: don't treat ip addresses as domain names</li>
<li><a
href="https://github.com/golang/net/commit/d1f64cc67036f272ea900194674afcf71eb3e816"><code>d1f64cc</code></a>
quic: use testing/synctest</li>
<li><a
href="https://github.com/golang/net/commit/fff0469cf57f71bea0cbc4cc8cbfb8f92be7a417"><code>fff0469</code></a>
http2: document that RFC 7540 prioritization does not work with small
payloads</li>
<li><a
href="https://github.com/golang/net/commit/f35e3a4dd2a34d1d47fac5b66210a40e2d374a79"><code>f35e3a4</code></a>
http2: fix weight overflow in RFC 7540 write scheduler</li>
<li><a
href="https://github.com/golang/net/commit/89adc90ac46a688eeda3a4a95b71acf073bd059c"><code>89adc90</code></a>
http2: fix typo referring to RFC 9218 as RFC 9128 instead</li>
<li><a
href="https://github.com/golang/net/commit/8d76a2c082f6f995c2ef1ce8a0d56f2e33b48092"><code>8d76a2c</code></a>
quic: don't defer MAX_STREAMS frames indefinitely</li>
<li><a
href="https://github.com/golang/net/commit/027f8b700eb72af5c0175a945535a42670628351"><code>027f8b7</code></a>
quic: fix expected ACK Delay in client's ACK after HANDSHAKE_DONE</li>
<li><a
href="https://github.com/golang/net/commit/dec9fe711ec1385a2aa169a3f8145d295abcca16"><code>dec9fe7</code></a>
dns/dnsmessage: update SVCB packing to prohibit name compression</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/net/compare/v0.46.0...v0.47.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/term` from 0.36.0 to 0.37.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/term/commit/1231d5465be98a7c5f01140358c142d365d4fbb6"><code>1231d54</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/term/commit/3475bc8ef1a53c8b2f1fa69d5f804135ca97f035"><code>3475bc8</code></a>
term: fix some comments</li>
<li>See full diff in <a
href="https://github.com/golang/term/compare/v0.36.0...v0.37.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/text` from 0.30.0 to 0.31.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/text/commit/e7ff6b3572e1a83c072ef150c985f86603986e1b"><code>e7ff6b3</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/text/commit/fbf012b8c1140cde0210e241356553d0000332e8"><code>fbf012b</code></a>
all: use reflect.TypeFor instead of reflect.TypeOf</li>
<li>See full diff in <a
href="https://github.com/golang/text/compare/v0.30.0...v0.31.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/tools` from 0.38.0 to 0.39.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/tools/commit/034e59c473362f8f2be47694d98fd3f12a1ad497"><code>034e59c</code></a>
internal/analysis/analyzerutil: fix FileUsesGoVersion</li>
<li><a
href="https://github.com/golang/tools/commit/076bd8052bceea0f0fdb90b2ec9205c8cbf5b00d"><code>076bd80</code></a>
gopls/internal/filewatcher: retry directory reading upon failure</li>
<li><a
href="https://github.com/golang/tools/commit/605803fb4494b25a23ab310776fea0fa1250f5c8"><code>605803f</code></a>
go/analysis/passes/loopclosure: simplify using IsMethodNamed</li>
<li><a
href="https://github.com/golang/tools/commit/2c6e03f2da11279a147c887c2babfa5daa8f8f02"><code>2c6e03f</code></a>
internal/testenv: allow Apple diff too</li>
<li><a
href="https://github.com/golang/tools/commit/82112c070f1367acf2fd846c2db5eb4208995893"><code>82112c0</code></a>
gopls/internal/settings: correct git issue for fieldalignment
warning</li>
<li><a
href="https://github.com/golang/tools/commit/1f978562b5d8e9396610d2b52f5e6c7584eb6eef"><code>1f97856</code></a>
go.mod: update golang.org/x dependencies</li>
<li><a
href="https://github.com/golang/tools/commit/c24121c97d900d2a5ba384cc97dedf0de3e18f34"><code>c24121c</code></a>
go/analysis/passes/modernize: stditerators: even better name
heuristic</li>
<li><a
href="https://github.com/golang/tools/commit/edb958762845d4f1feb4ec79582b2ea8b02533be"><code>edb9587</code></a>
go/analysis/passes/modernize: stditerators: better name heuristic</li>
<li><a
href="https://github.com/golang/tools/commit/2f6a4f9b3cb8896e8e9cd7c18d610299d0e92b32"><code>2f6a4f9</code></a>
go/analysis/passes/modernize: forvar: handle &quot;if v := v; cond
{&quot;</li>
<li><a
href="https://github.com/golang/tools/commit/efd8c43777a5aace999c8162ee81f4b8c9c0695c"><code>efd8c43</code></a>
go/analysis: don't apply fixes to generated files</li>
<li>Additional commits viewable in <a
href="https://github.com/golang/tools/compare/v0.38.0...v0.39.0">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-11-17 12:14:53 +00:00
dependabot[bot] 04cf5f8690 chore: bump google.golang.org/api from 0.255.0 to 0.256.0 (#20794)
Bumps
[google.golang.org/api](https://github.com/googleapis/google-api-go-client)
from 0.255.0 to 0.256.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.256.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.255.0...v0.256.0">0.256.0</a>
(2025-11-10)</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/3366">#3366</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/997c613e70ddbf1483e4212641cb09db86f7716b">997c613</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3368">#3368</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/57e958d22096bca64db83dc7888f248f0d8a6bc4">57e958d</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3369">#3369</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/5d436f7172766d9dab04cfcf3dd0e5054228a084">5d436f7</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3370">#3370</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/140a610ace04e635f919acf8f7a5441d1d4546b9">140a610</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3371">#3371</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/39a2bc07bfc4693cf0a99de0fe70807783471e99">39a2bc0</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.255.0...v0.256.0">0.256.0</a>
(2025-11-10)</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/3366">#3366</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/997c613e70ddbf1483e4212641cb09db86f7716b">997c613</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3368">#3368</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/57e958d22096bca64db83dc7888f248f0d8a6bc4">57e958d</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3369">#3369</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/5d436f7172766d9dab04cfcf3dd0e5054228a084">5d436f7</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3370">#3370</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/140a610ace04e635f919acf8f7a5441d1d4546b9">140a610</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3371">#3371</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/39a2bc07bfc4693cf0a99de0fe70807783471e99">39a2bc0</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/811ba14d5fc1b87bd0058d49b80293164db986fa"><code>811ba14</code></a>
chore(main): release 0.256.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3367">#3367</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/11afd811cc00001a2691e5086db1824d94c141cb"><code>11afd81</code></a>
chore(all): update all (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3372">#3372</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/39a2bc07bfc4693cf0a99de0fe70807783471e99"><code>39a2bc0</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3371">#3371</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/140a610ace04e635f919acf8f7a5441d1d4546b9"><code>140a610</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3370">#3370</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/5d436f7172766d9dab04cfcf3dd0e5054228a084"><code>5d436f7</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3369">#3369</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/57e958d22096bca64db83dc7888f248f0d8a6bc4"><code>57e958d</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3368">#3368</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/997c613e70ddbf1483e4212641cb09db86f7716b"><code>997c613</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3366">#3366</a>)</li>
<li>See full diff in <a
href="https://github.com/googleapis/google-api-go-client/compare/v0.255.0...v0.256.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.255.0&new-version=0.256.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-17 12:14:37 +00:00
Ethan 897286f335 test: fix flake in scaletest/workspaceupdates/TestRun (#20773)
Closes https://github.com/coder/internal/issues/1127

In the workspace updates scaletest load generator, we end the test once all clients have seen a workspace update for their workspace. These workspace updates are generated when the workspace is created, NOT when the workspace build has finished. 
This means when the runner goes to clean up the workspaces, they may still be building. The runner attempts to address this by cancelling the build, but that fails with a 403 since the runner users don't have permission.

The fix is to simply always wait for the build to finish, regardless of whether we were able to successfully cancel it.
In this test it's probably faster to just wait for the build to finish then the overhead of cancelling it, so that's what I've gone with here.
2025-11-17 12:00:07 +11:00
Michael Suchacz 5ee39e88a3 chore: rename cmux to mux in the dogfood template (#20787)
<!--

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-16 00:49:06 +01:00
Mathias Fredriksson fa314fe7e5 fix(coderd/database): rename duplicate migration 397 to 398 (#20783)
Fix duplicate migration from #20683.
2025-11-14 18:05:29 +00:00
Mathias Fredriksson 1483fd11ff fix(coderd/database): improve task status in tasks_with_status view (#20683)
This change restructures the `tasks_with_status` view query to:

- Improve debuggability by adding a `status_debug` column to better
understand the outcome
- Reduce clutter from `bool_or`, `bool_and` which are aggregate
functions that did not actually have serve a purpose (each join is 0-1
rows)
- Improve agent lifecycle state coverage, `start_timeout` and
`start_error` were omitted
- These states are easy to trigger even in a perfectly functioning
workspace/task so we now rely on app health to report whether or not
there was an issue
- Mark canceling and canceled workspace build jobs as error state
- Agent stop states were implicitly `unknown`, now there are explicit (I
initially considered `error`, could go either way)
2025-11-14 19:52:26 +02:00
Jaayden Halko 6067aa3aa1 fix: correctly set touched for autofill dynamic parameters (#20769)
this resolves #20187 

This bug was introduced in PR https://github.com/coder/coder/pull/18894
in CreateWorkspacePageViewExperimental.tsx

This PR made a change so that the entire parameter was used instead of
just the parameter name to mark an autofilled parameter as touched.

The fix here is to just use the parameter name.
2025-11-14 17:09:06 +00:00
Steven Masley f23836d426 chore: add more scopes to the curated catalog (#20746)
Just noticed when writing docs. These are probably obvious scopes to
allow
2025-11-14 08:30:10 -06:00
35C4n0r da9214e212 chore: add opencode icon (#20670)
Co-authored-by: 35C4n0r <work.jkmr@gmail.com>
2025-11-14 13:07:20 +00:00
Susana Ferreira 79d46769fe chore: remove warning for non-trackable workspace builds in metrics (#20775)
Previously, `UpdateWorkspaceTimingsMetrics` would log a warning for
workspace builds that aren't tracked (restarts, stops, subsequent builds
after creation). This was noisy since these are legitimate operations,
not errors.

`UpdateWorkspaceTimingsMetrics` is specifically designed to track only
workspace creation, prebuild creation, and prebuild claim timings.

Related with: https://github.com/coder/coder/pull/20772
2025-11-14 12:26:32 +00:00
Danny Kopping 86c4948445 chore: add timing flag context to warn message (#20772)
`prometheus.provisionerd_server_metrics: unsupported workspace timing
flags` appears in the logs, but without knowledge of the available flags
it's not possible to troubleshoot this.

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-14 10:10:53 +00:00
Ethan 6bafbb7bc5 feat(cli): add prebuilds scaletest command (#20600)
Closes https://github.com/coder/internal/issues/914
2025-11-14 18:08:14 +11:00
Ethan b31d09865e feat(scaletest): add runner for prebuilds (#20571)
Relates to https://github.com/coder/internal/issues/914

Adds a runner for scaletesting prebuilds. The runner uploads a no-op template with prebuilds, watches for the corresponding workspaces to be created, and then does the same to tear them down. I didn't originally plan on having metrics for the teardown, but I figured we might as well as it's still the same prebuilds reconciliation loop mechanism being tested.
2025-11-14 17:57:22 +11:00
Steven Masley fe3b825b86 chore: per template opt into cached terraform directories (#20609)
For experimental and dogfood purposes, this adds the ability to opt in a single template. 
Leaving the rest of the templates as is. 

For GA, this setting might be removed or changed.
2025-11-13 14:04:12 -06:00
Paweł Banaszewski edf056babc test: add mocked terraform installation files (#20757)
Adds mocked terraform installation files and uses them in
provisioner/terraform.TestInstall
Fixes: https://github.com/coder/internal/issues/72
2025-11-13 20:14:53 +01:00
Steven Masley 9ca5b44b56 chore: implement persistent terraform directories (experimental) (#20563)
Prior to this, every workspace build ran `terraform init` in a fresh
directory. This would mean the `modules` are downloaded fresh. If the
module is not pinned, subsequent workspace builds would have different
modules.
2025-11-13 07:50:17 -06:00
Jaayden Halko 14f08444a9 fix: send all params instead of only touched params (#20740)
resolves #20257

Ensure all parameters are sent in the web socket request instead of only
touched parameters.

Using touched parameters is irrelevant for the workspace parameters page
in workspace settings because parameters that appear here have already
been chosen by the user during workspace creation. So all parameters
should be sent in the web socket request whether have been touched in
the form or not.
2025-11-13 13:00:12 +00:00
Spike Curtis a3c851c0e6 feat: add task status reporting load generator runner (#20538)
Adds the Runner, Config, and Metrics for the scaletest load generator for task status.

Part of https://github.com/coder/internal/issues/913
2025-11-13 16:53:02 +04:00
david-fraley 5bfbb0301f chore: update release calendar for new patches (#20748) 2025-11-13 17:22:42 +05:00
Jake Howell f559e51d7f feat: add duration to the Request Logs details (#20756)
This pull-request simply implements a new field within our `Request
Log`s details view where-in we describe back to the user how long their
request took based on the `end_date - start_date` in a human-like way.
Users can hover the value to see the `title=` for the true value.

<img width="2358" height="936" alt="CleanShot 2025-11-13 at 11 51 56@2x"
src="https://github.com/user-attachments/assets/f69c87cd-2735-4e03-9fc8-ae0f4d94b5d1"
/>
2025-11-13 12:29:03 +11:00
Dean Sheather a8f2a8a44d fix(cli): skip dry-run for workspace start/restart commands (#20754)
## Problem

The `prepWorkspaceBuild()` function in `cli/create.go` was
unconditionally executing dry-runs for **all** workspace actions. This
caused unnecessary delays and "Planning workspace..." messages during
`coder start` and `coder restart` commands when they should only happen
during `coder create` and `coder update`.

## Root Cause

The `prepWorkspaceBuild()` function is shared code called by:
- **create command** - passes `WorkspaceCreate` action  dry-run IS
desired
- **update command** - passes `WorkspaceUpdate` action  dry-run IS
desired
- **start command** - passes `WorkspaceStart` action (or
`WorkspaceUpdate` as fallback)  dry-run NOT desired for
`WorkspaceStart`
- **restart command** - passes `WorkspaceRestart` action  dry-run NOT
desired
- **scaletest commands** - pass `WorkspaceCreate` action  dry-run IS
desired

## Solution

Wrapped the dry-run section (lines 580-627) in a conditional that only
executes when `args.Action == WorkspaceCreate || args.Action ==
WorkspaceUpdate`.

This skips dry-run for `WorkspaceStart` and `WorkspaceRestart` actions
while preserving it for creation and explicit updates.

## Changes

- Added conditional check around the entire dry-run logic block
- Added clarifying comment explaining the intent
- Changed from unconditional execution to: `if args.Action ==
WorkspaceCreate || args.Action == WorkspaceUpdate { ... }`

## Impact

| Command | Action Type | Dry-run Before | Dry-run After | Status |
|---------|-------------|----------------|---------------|--------|
| `coder create` | `WorkspaceCreate` |  Yes |  Yes | Unchanged |
| `coder update` | `WorkspaceUpdate` |  Yes |  Yes | Unchanged |
| `coder start` (normal) | `WorkspaceStart` |  Yes (bug) |  No |
**Fixed** |
| `coder start` (template changed) | `WorkspaceUpdate` |  Yes |  Yes |
Unchanged (correct behavior) |
| `coder restart` | `WorkspaceRestart` |  Yes (bug) |  No | **Fixed**
|
| scaletest | `WorkspaceCreate` |  Yes |  Yes | Unchanged |

## Testing

 **Code compiles successfully**
```bash
go build -o /dev/null ./cli/...
```

 **All relevant tests pass locally**
```bash
cd cli && go test -run "TestCreate|TestStart|TestRestart|TestUpdate" -v
PASS
ok      github.com/coder/coder/v2/cli   3.337s
```

 **All CI checks pass**
- test-go-pg (ubuntu, macos, windows) 
- test-go-pg-17 
- test-go-race-pg 
- test-e2e 
- All other checks 

## Behavior Changes

**Before:**
- Users running `coder start` would see "Planning workspace..." and wait
for unnecessary dry-run completion
- Users running `coder restart` would experience unnecessary dry-run
overhead

**After:**
- `coder start` (simple start) skips dry-run entirely (faster, more
intuitive)
- `coder start` (with template update) still shows dry-run (correct -
user needs to see what's changing)
- `coder restart` skips dry-run entirely (faster, more intuitive)
- `coder create` maintains existing dry-run behavior (shows "Planning
workspace..." and resource preview)
- `coder update` maintains existing dry-run behavior (shows "Planning
workspace..." and resource preview)

## Verification

Manual testing should verify:
1. `coder create` still shows "Planning workspace..." 
2. `coder update` still shows "Planning workspace..." 
3. `coder start` (simple start) does NOT show "Planning workspace..." 
4. `coder restart` does NOT show "Planning workspace..." 
2025-11-13 09:48:28 +11:00
Steven Masley 04727c06e8 chore: add experiment toggle for terraform workspace caching (#20559)
Experiments passed to provisioners to determine behavior. This adds
`--experiments` flag to provisioner daemons. Prior to this, provisioners
had no method to turn on/off experiments.
2025-11-12 14:26:15 -06:00
Andrew Aquino ac2c161636 fix(docs): add newlines to display GFM alerts correctly (#20747)
Fixes this bug called out by @matifali on
https://coder.com/docs/ai-coder/tasks:
<img width="718" height="165" alt="image"
src="https://github.com/user-attachments/assets/5ac5c70d-c677-44f6-984d-8538a8e7c6cc"
/>

[The docs for GFM
alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)
specify that the alert type (`[!NOTE]`, `[!IMPORTANT]`, etc) should be
on its own line within the blockquote, with the alert text on the
following line(s).
2025-11-12 11:11:51 -08:00
Steven Masley 9149c1e9f2 chore: append template metadata to protobuf config (#20558)
Adds some extra meta data sent to provisioners. Also adds a field
`reuse_terraform_workspace` to tell the provisioner whether or not to
use the caching experiment.
2025-11-12 12:46:39 -06:00
Zach 5e85663ce3 feat(cli): add macOS support for session token keyring storage (#20613)
Add support for storing the CLI session token in the OS keyring on macOS
when the --use-keyring flag is provided.

https://github.com/coder/coder/issues/19403

https://www.notion.so/coderhq/CLI-Session-Token-in-OS-Keyring-293d579be592808b8b7fd235304e50d5
2025-11-12 10:48:19 -07:00
Steven Masley c47b437c12 chore: comment no-lint on gosec for unsafe zip extracting (#20741) 2025-11-12 10:42:16 -06:00
Steven Masley 7c8deaf0d6 chore: refactor terraform paths to a central structure (#20566)
Refactors all Terraform file path logic into a centralized tfpath package. This consolidates all path construction into a single, testable Layout type. 

Instead of passing around `string` for directories, pass around the `Layout` which has the file location methods on it.
2025-11-12 09:24:07 -06:00
Danny Kopping c69eb7c157 docs: reflect steps required to enable coder MCP tool injection (#20735)
Follow-up from #20713

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-12 12:02:04 +00:00
Danny Kopping d49545070c fix: upgrade aibridge lib to fix cache issue (#20730)
https://github.com/coder/aibridge/pull/49 fixed an issue with tool
ordering which was busting the cache and leading to increased costs

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-12 13:17:33 +02:00
Cian Johnston f59763968f ci(.github/workflows/traiage.yaml): adjust TASK_PROMPT (#20733)
Adjusts instructions for the trAIage workflow to balance autonomy and
correctness.
2025-11-12 11:14:20 +00:00
Spike Curtis 6dbde523ae fix: omit body field from SDK client request/response logs when not logging bodies (#20729)
In SDK request logs, when we don't enable LogBodies, before this change it looks in the logs like we are sending empty bodies.

```
2025-11-08 01:03:54.710 [debu]  sdk request  method=POST  url=https://coder.example/api/v2/workspaceagents/aws-instance-identity  body=""
2025-11-08 01:03:54.765 [debu]  sdk response  method=POST  url=https://coder.example/api/v2/workspaceagents/aws-instance-identity  status=400  body=""  trace_id=""  span_id=""
```

This changes our request and response logging so we omit the `body` field when not logging bodies, rather than show a misleading empty string.
2025-11-12 14:37:22 +04:00
Susana Ferreira ca94588bd5 fix: send prebuild job notification after job build db commit (#20693)
## Problem

Fix race condition in prebuilds reconciler. Previously, a job
notification event was sent to a Go channel before the provisioning
database transaction completed. The notification is consumed by a
separate goroutine that publishes to PostgreSQL's LISTEN/NOTIFY, using a
separate database connection. This creates a potential race: if a
provisioner daemon receives the notification and queries for the job
before the provisioning transaction commits, it won't find the job in
the database.

This manifested as a flaky test failure in `TestReinitializeAgent`,
where provisioners would occasionally miss newly created jobs. The test
uses a 25-second timeout context, while the acquirer's backup polling
mechanism checks for jobs every 30 seconds. This made the race condition
visible in tests, though in production the backup polling would
eventually pick up the job. The solution presented here guarantees that
a job notification is only sent after the provisioning database
transaction commits.

## Changes

* The `provision()` and `provisionDelete()` functions now return the
provisioner job instead of sending notifications internally.
* A new `publishProvisionerJob()` helper centralizes the notification
logic and is called after each transaction completes.

Closes: https://github.com/coder/internal/issues/963
2025-11-12 10:36:39 +00:00
Mathias Fredriksson e61b0fcf42 chore(codersdk): deprecate HasAITask on WorkspaceBuild (#20732)
Closes coder/internal#973
2025-11-12 10:27:06 +00:00
Danny Kopping 04f809f2d0 chore!: allow coder MCP tools to not be injected (#20713)
Currently, when AI Bridge is enabled AND the `oauth2` and
`mcp-server-http` experiments are enabled we inject Coder's MCP tools
into all intercepted AI Bridge requests.

This PR introduces a config to control this behaviour.

**NOTE:** this is a backwards-incompatible change; previously these
tools would be injected automatically, now this setting will need to be
explicitly enabled.

---------

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-12 11:23:01 +02:00
Kacper Sawicki f543a87b78 chore: cache terraform providers for workspaces terraform tests (#20603)
Fixes flaky `TestWorkspaceTagsTerraform` and
`TestWorkspaceTemplateParamsChange` tests that were failing with
`connection reset by peer` errors when downloading the coder/coder
provider.

This applies the same caching solution which was done in
https://github.com/coder/coder/pull/17373

1. Extracts provider caching logic into `testutil/terraform_cache.go`
2. Updates TestProvision to use the shared caching helpers
3. Updates enterprise workspace tests to use the shared caching helpers

The cache is persisted at `~/.cache/coderv2-test/` and automatically
cached between CI runs via existing GitHub Actions cache setup.

Closes https://github.com/coder/internal/issues/607
2025-11-12 08:43:22 +00:00
Ethan e49c917bb0 perf: use a single query for notification target lookups (#20574)
Somewhat minor inefficiency in notifications I discovered during a scaletest where I was creating many users. Our `GetUsers` query filter for rbac roles uses the `&&` operator on arrays, which is the intersection of the two arrays. Despite that, we were making seperate DB queries for each role, and then collating the results. I didn't see any other instances of this.

The test changes are required as the order of outgoing notifications is now non-deterministic.
2025-11-11 21:23:23 -05:00
Jake Howell 903c045b9c fix: retain searchParams in paginatedInterceptions during filter updates (#20725)
This pull-request ensures that when we attempt to navigate in-between
pages or actually attempt to update the filters that they will persist
as we expect. This was also causing an issue where on first load (or
where it lacked `page=1` to be specific) that these would seem to lose
their input.
2025-11-12 13:08:40 +11:00
Jake Howell 3bb7975a17 feat: add page for ai-bridge interception logs (#20331)
Relates #20287 

This pull-request introduces a basic routing for `AI Governance`'s
Request Logs feature. Currently we're just pulling back the basics from
the database and rendering it into the table. Nothing exciting.

The idea is to extend further upon the `/aigovernance` route so it has
been appropriately wrapped with a `<AIGovernanceLayout />` to introduce
a navigation later.
2025-11-12 11:41:41 +11:00
Spike Curtis dc21699e8c fix: use correct slog arguments (#20721)
Fixes a bad slog.Error() command that didn't wrap the error in `slog.Error`
2025-11-11 22:44:48 +04:00
Atif Ali 086d6b8719 chore(docs): update links and minor improvements to AI Bridge (#20714)
Co-authored-by: Danny Kopping <danny@coder.com>
2025-11-11 15:13:38 +00:00
Atif Ali f1fad60f9f chore: add openai.com patterns to linkspector config (#20716) 2025-11-11 20:03:57 +05:00
Cian Johnston b6935c3528 chore(docs/ai-coder): add migration guide for provider version 2.13.0 (#20426)
Closes https://github.com/coder/internal/issues/1080

---------

Co-authored-by: Ben Potter <ben@coder.com>
2025-11-11 09:07:41 +00:00
Spike Curtis e96ab0ef59 test: fix PingDirect test tear down (#20687)
Fixes https://github.com/coder/internal/issues/66

The problem is a race during test tear down where the node callback can fire after the destination tailnet.Conn has already closed, causing an error.

The fix I have employed is to remove the callback in a t.Cleanup() and also refactor some tests to ensure they close the tailnet.Conn in a Cleanup deeper in the stack.
2025-11-11 10:34:31 +04:00
Atif Ali c21b3e49b3 docs: add client configuration section and support matrix for AI Bridge (#20640)
Revised the AI Bridge documentation to clarify provider configuration
steps, including new sections for OpenAI, Anthropic, and Amazon Bedrock.
Added details on pre-configuring templates and using AI Bridge with
Coder Tasks. Introduced a new image illustrating the AI Bridge
implementation details. Updated compatibility notes for various AI
clients.

Addresses coder/aibridge#4

Preview:
https://coder.com/docs/@aibridge-client-instructions/ai-coder/ai-bridge

---------

Co-authored-by: david-fraley <67079030+david-fraley@users.noreply.github.com>
Co-authored-by: Danny Kopping <danny@coder.com>
Co-authored-by: David Fraley <davidiii@fraley.us>
2025-11-10 22:24:37 +00:00
Jaayden Halko 47c703aa4d refactor: migrate CopyableValue from MUI to Radix UI (#20261)
## Summary

Migrates the `CopyableValue` component from Material-UI Tooltip to Radix
UI Tooltip.

## Changes

### CopyableValue Component
- **Removed unused prop**: `PopperProps` (never used in any call site)
- **Renamed prop**: `placement` → `side` (Radix naming convention)
- **Updated pattern**: Now uses
TooltipProvider/Tooltip/TooltipTrigger/TooltipContent composition

**Minimal API surface change:**
- `placement` prop renamed to `side` (only affects 1 call site - already
updated)
- `PopperProps` removed (was never used)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-10 22:15:40 +00:00
Danielle Maywood f2a1a7e8c3 fix(coderd): gate AI task notifications on agent ready state (#20690)
Relates to https://github.com/coder/internal/issues/1098

Currently AgentAPI waits for only 2 seconds worth of identical terminal
screen snapshots before deciding a task has entered a "stable" state. We
interpret this as becoming "idle", resulting in a notification being
triggered. This behavior is not ideal and is ultimately the root cause
of our spammy notifications.

Unfortunately, until we move AgentAPI to either use the Claude Code SDK
(or ACP wrapper around it), we are unable to easily fix the root cause.

This PR instead waits until the agent is ready before it will send state
change notifications. This will at least resolve _some_ of the
complaints about task state notifications being too spammy.

---

🤖 PR was written by Claude Sonnet 4.5 using [Coder
Mux](https://github.com/coder/cmux) and reviewed by a human 👩
2025-11-10 16:00:13 +00:00
dependabot[bot] 616db320d7 chore: bump github.com/anthropics/anthropic-sdk-go from 1.16.0 to 1.17.0 (#20701)
Bumps
[github.com/anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go)
from 1.16.0 to 1.17.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.17.0</h2>
<h2>1.17.0 (2025-11-05)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.16.0...v1.17.0">v1.16.0...v1.17.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>bedrock:</strong> re-route beta headers through request body
(<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/00a2bf35b34aa49f1514493cf0638b467c4f4eec">00a2bf3</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>internal:</strong> grammar fix (it's -&gt; its) (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/687bc299cacb84349eb2684df46994c06f9ba962">687bc29</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.17.0 (2025-11-05)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.16.0...v1.17.0">v1.16.0...v1.17.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>bedrock:</strong> re-route beta headers through request body
(<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/00a2bf35b34aa49f1514493cf0638b467c4f4eec">00a2bf3</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>internal:</strong> grammar fix (it's -&gt; its) (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/687bc299cacb84349eb2684df46994c06f9ba962">687bc29</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/96a1a9111312e638c0c12f071411b5035aaaf4e0"><code>96a1a91</code></a>
release: 1.17.0</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/3673a82c24a80355f2de0e64261001afc216ae0a"><code>3673a82</code></a>
chore(internal): grammar fix (it's -&gt; its)</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/44420226087d294fdc28291d48e7c8cc04beae49"><code>4442022</code></a>
add test</li>
<li>See full diff in <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.16.0...v1.17.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.16.0&new-version=1.17.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-10 15:32:01 +00:00
dependabot[bot] 02974935b9 chore: bump rust from af95fd1 to d9ba801 in /dogfood/coder (#20706)
Bumps rust from `af95fd1` to `d9ba801`.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rust&package-manager=docker&previous-version=slim&new-version=slim)](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-10 14:35:17 +00:00
dependabot[bot] 476df47d98 chore: bump github.com/coder/terraform-provider-coder/v2 from 2.12.0 to 2.13.1 (#20697)
Bumps
[github.com/coder/terraform-provider-coder/v2](https://github.com/coder/terraform-provider-coder)
from 2.12.0 to 2.13.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/coder/terraform-provider-coder/releases">github.com/coder/terraform-provider-coder/v2's
releases</a>.</em></p>
<blockquote>
<h2>v2.13.1</h2>
<h2>What's Changed</h2>
<blockquote>
<p>Note: There are no functional changes between this release and
<code>v2.13.0-pre0</code>.</p>
</blockquote>
<ul>
<li>chore(README.md): add note regarding multiple tags by <a
href="https://github.com/johnstcn"><code>@​johnstcn</code></a> in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/461">coder/terraform-provider-coder#461</a></li>
<li>chore(integration): fix failing coder-ai-task integration test by <a
href="https://github.com/johnstcn"><code>@​johnstcn</code></a> in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/456">coder/terraform-provider-coder#456</a></li>
<li>chore(deps): update Go version to 1.24.6 by <a
href="https://github.com/michaelvp411"><code>@​michaelvp411</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/453">coder/terraform-provider-coder#453</a></li>
<li>fix: set default value for <code>coder_ai_task.prompt</code> to an
empty string by <a
href="https://github.com/DanielleMaywood"><code>@​DanielleMaywood</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/458">coder/terraform-provider-coder#458</a></li>
<li>feat: add <code>enabled</code> computed field to
<code>coder_ai_task</code> by <a
href="https://github.com/DanielleMaywood"><code>@​DanielleMaywood</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/451">coder/terraform-provider-coder#451</a></li>
<li>build(deps): Bump goreleaser/goreleaser-action from 6.3.0 to 6.4.0
by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/427">coder/terraform-provider-coder#427</a></li>
<li>feat: add coder_task data source by <a
href="https://github.com/johnstcn"><code>@​johnstcn</code></a> in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/460">coder/terraform-provider-coder#460</a></li>
<li>docs(coder_ai_task): add min coder version for <code>prompt</code>
and <code>enabled</code> by <a
href="https://github.com/DanielleMaywood"><code>@​DanielleMaywood</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/459">coder/terraform-provider-coder#459</a></li>
<li>chore(README.md): add note regarding multiple tags by <a
href="https://github.com/johnstcn"><code>@​johnstcn</code></a> in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/461">coder/terraform-provider-coder#461</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/michaelvp411"><code>@​michaelvp411</code></a>
made their first contribution in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/453">coder/terraform-provider-coder#453</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/coder/terraform-provider-coder/compare/v2.12.0...v2.13.1">https://github.com/coder/terraform-provider-coder/compare/v2.12.0...v2.13.1</a></p>
<h2>v2.13.0-pre0</h2>
<h2>What's Changed</h2>
<ul>
<li>chore(integration): fix failing coder-ai-task integration test by <a
href="https://github.com/johnstcn"><code>@​johnstcn</code></a> in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/456">coder/terraform-provider-coder#456</a></li>
<li>chore(deps): update Go version to 1.24.6 by <a
href="https://github.com/michaelvp411"><code>@​michaelvp411</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/453">coder/terraform-provider-coder#453</a></li>
<li>fix: set default value for <code>coder_ai_task.prompt</code> to an
empty string by <a
href="https://github.com/DanielleMaywood"><code>@​DanielleMaywood</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/458">coder/terraform-provider-coder#458</a></li>
<li>feat: add <code>enabled</code> computed field to
<code>coder_ai_task</code> by <a
href="https://github.com/DanielleMaywood"><code>@​DanielleMaywood</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/451">coder/terraform-provider-coder#451</a></li>
<li>build(deps): Bump goreleaser/goreleaser-action from 6.3.0 to 6.4.0
by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/427">coder/terraform-provider-coder#427</a></li>
<li>feat: add coder_task data source by <a
href="https://github.com/johnstcn"><code>@​johnstcn</code></a> in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/460">coder/terraform-provider-coder#460</a></li>
<li>docs(coder_ai_task): add min coder version for <code>prompt</code>
and <code>enabled</code> by <a
href="https://github.com/DanielleMaywood"><code>@​DanielleMaywood</code></a>
in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/459">coder/terraform-provider-coder#459</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/michaelvp411"><code>@​michaelvp411</code></a>
made their first contribution in <a
href="https://redirect.github.com/coder/terraform-provider-coder/pull/453">coder/terraform-provider-coder#453</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/coder/terraform-provider-coder/compare/v2.12.0...v2.13.0-pre0">https://github.com/coder/terraform-provider-coder/compare/v2.12.0...v2.13.0-pre0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/5c4def2ee8c73b210c9e345bba86263bfdc66437"><code>5c4def2</code></a>
chore(README.md): add note regarding multiple tags (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/461">#461</a>)</li>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/297687916cce0bc942ef85063485f77b33292ddd"><code>2976879</code></a>
docs(coder_ai_task): add min coder version for <code>prompt</code> and
<code>enabled</code> (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/459">#459</a>)</li>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/5fe8d857e52a2bcc84ae10d46a85491361fe2d63"><code>5fe8d85</code></a>
feat: add coder_task data source (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/460">#460</a>)</li>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/e0b1ec1db3b93bfc3c9f1ee1ecf4a6c825d4310a"><code>e0b1ec1</code></a>
build(deps): Bump goreleaser/goreleaser-action from 6.3.0 to 6.4.0 (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/427">#427</a>)</li>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/1211f288075b8b04a30864833cf447f9a82ec8ba"><code>1211f28</code></a>
feat: add <code>enabled</code> computed field to
<code>coder_ai_task</code> (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/451">#451</a>)</li>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/fc9724be572ff7d97eb9d6af4ffd90c587a43e28"><code>fc9724b</code></a>
fix: set default value for <code>coder_ai_task.prompt</code> to an empty
string (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/458">#458</a>)</li>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/a86ce822bdc80aaf10178f78e159359a28a4d9a9"><code>a86ce82</code></a>
chore(deps): update Go version to 1.24.6 (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/453">#453</a>)</li>
<li><a
href="https://github.com/coder/terraform-provider-coder/commit/979aeb5bfdeb58c8da278988fb3eeae4b90f511d"><code>979aeb5</code></a>
chore(integration): fix failing coder-ai-task integration test (<a
href="https://redirect.github.com/coder/terraform-provider-coder/issues/456">#456</a>)</li>
<li>See full diff in <a
href="https://github.com/coder/terraform-provider-coder/compare/v2.12.0...v2.13.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/coder/terraform-provider-coder/v2&package-manager=go_modules&previous-version=2.12.0&new-version=2.13.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-11-10 14:07:21 +00:00
dependabot[bot] ea00a993cd chore: bump google.golang.org/api from 0.254.0 to 0.255.0 (#20699)
Bumps
[google.golang.org/api](https://github.com/googleapis/google-api-go-client)
from 0.254.0 to 0.255.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.255.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.254.0...v0.255.0">0.255.0</a>
(2025-11-04)</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/3357">#3357</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/430bc4639d14b3c7969981603891163421883695">430bc46</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3359">#3359</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/0bcacee13f1bd305cf1e16bfb714fbe998b7fcb1">0bcacee</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3360">#3360</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/c9cdcadebd1ac3e2de3c0146b3a1d6eb0956c3fc">c9cdcad</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3361">#3361</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/acdddcdc891d41f9ac22bcf031d53f9f17810637">acdddcd</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3362">#3362</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/040f8aaadedfcf6fb449937e734f3c57a3cfedd4">040f8aa</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3364">#3364</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/8f13004c104b3620144017f36886ef3818878dad">8f13004</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3365">#3365</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/4ea8be06ce628f4af4949c6954e1342c0db8e76b">4ea8be0</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.254.0...v0.255.0">0.255.0</a>
(2025-11-04)</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/3357">#3357</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/430bc4639d14b3c7969981603891163421883695">430bc46</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3359">#3359</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/0bcacee13f1bd305cf1e16bfb714fbe998b7fcb1">0bcacee</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3360">#3360</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/c9cdcadebd1ac3e2de3c0146b3a1d6eb0956c3fc">c9cdcad</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3361">#3361</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/acdddcdc891d41f9ac22bcf031d53f9f17810637">acdddcd</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3362">#3362</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/040f8aaadedfcf6fb449937e734f3c57a3cfedd4">040f8aa</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3364">#3364</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/8f13004c104b3620144017f36886ef3818878dad">8f13004</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3365">#3365</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/4ea8be06ce628f4af4949c6954e1342c0db8e76b">4ea8be0</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/d7491ba2192f77c16f3a76c381ace9ff568a5f46"><code>d7491ba</code></a>
chore(main): release 0.255.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3358">#3358</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/4ea8be06ce628f4af4949c6954e1342c0db8e76b"><code>4ea8be0</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3365">#3365</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/5d5029ab3bcc8e24c1f47e73335127732c8da81b"><code>5d5029a</code></a>
chore(all): update all to ab9386a (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3363">#3363</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/8f13004c104b3620144017f36886ef3818878dad"><code>8f13004</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3364">#3364</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/040f8aaadedfcf6fb449937e734f3c57a3cfedd4"><code>040f8aa</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3362">#3362</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/acdddcdc891d41f9ac22bcf031d53f9f17810637"><code>acdddcd</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3361">#3361</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/c9cdcadebd1ac3e2de3c0146b3a1d6eb0956c3fc"><code>c9cdcad</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3360">#3360</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/0bcacee13f1bd305cf1e16bfb714fbe998b7fcb1"><code>0bcacee</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3359">#3359</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/430bc4639d14b3c7969981603891163421883695"><code>430bc46</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3357">#3357</a>)</li>
<li>See full diff in <a
href="https://github.com/googleapis/google-api-go-client/compare/v0.254.0...v0.255.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.254.0&new-version=0.255.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-10 14:06:24 +00:00
dependabot[bot] 51bac75584 chore: bump the x group with 3 updates (#20696)
Bumps the x group with 3 updates:
[golang.org/x/oauth2](https://github.com/golang/oauth2),
[golang.org/x/sync](https://github.com/golang/sync) and
[golang.org/x/sys](https://github.com/golang/sys).

Updates `golang.org/x/oauth2` from 0.32.0 to 0.33.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/oauth2/commit/f28b0b5467dda26d56f1240381158f7c334654d1"><code>f28b0b5</code></a>
all: fix some comments</li>
<li><a
href="https://github.com/golang/oauth2/commit/fd15e0fe894866ebff17ca3503d3706a967b061a"><code>fd15e0f</code></a>
x/oauth2: populate RetrieveError from DeviceAuth</li>
<li>See full diff in <a
href="https://github.com/golang/oauth2/compare/v0.32.0...v0.33.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/sync` from 0.17.0 to 0.18.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/sync/commit/1966f539bbd7664efd5bb7462ae94d9db67f4502"><code>1966f53</code></a>
errgroup: fix some typos in comment</li>
<li>See full diff in <a
href="https://github.com/golang/sync/compare/v0.17.0...v0.18.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `golang.org/x/sys` from 0.37.0 to 0.38.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/golang/sys/commit/15129aafc3056028aa2694528ac20373f8cd34e4"><code>15129aa</code></a>
cpu: also use MRS instruction in getmmfr1</li>
<li><a
href="https://github.com/golang/sys/commit/ed38ca2d414bb2d894e2622d358503d9eec7e29a"><code>ed38ca2</code></a>
unix: add SizeofNhmsg and SizeofNexthopGrp</li>
<li><a
href="https://github.com/golang/sys/commit/3675c4cc48d381cf54212e0aea81448a272d7c01"><code>3675c4c</code></a>
cpu: use MRS instruction to read arm64 system registers</li>
<li><a
href="https://github.com/golang/sys/commit/2a152728509e3d145921d5fb44d056fb0a9c1386"><code>2a15272</code></a>
unix: add consts for ELF handling</li>
<li><a
href="https://github.com/golang/sys/commit/6239615695530c23a1927a4c02a1e8a401b79c94"><code>6239615</code></a>
cpu: add HPDS, LOR, PAN detection for arm64</li>
<li><a
href="https://github.com/golang/sys/commit/ea436ef09d96eabb81a7a9aa95e7b57c793c6855"><code>ea436ef</code></a>
windows: add iphlpapi routing functions</li>
<li><a
href="https://github.com/golang/sys/commit/28c5bda5d46d6d11e1f40ed60f85cc10546be096"><code>28c5bda</code></a>
unix: add SetMemPolicy and its mode/flag values</li>
<li><a
href="https://github.com/golang/sys/commit/b731f782ac28e6f05f3d85d2ee1e207460ee93d0"><code>b731f78</code></a>
unix/linux: switch to ubuntu 25.04, Go 1.25.1</li>
<li>See full diff in <a
href="https://github.com/golang/sys/compare/v0.37.0...v0.38.0">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-11-10 14:06:10 +00:00
dependabot[bot] 219db42984 chore: bump github.com/brianvoe/gofakeit/v7 from 7.8.0 to 7.9.0 (#20698)
Bumps
[github.com/brianvoe/gofakeit/v7](https://github.com/brianvoe/gofakeit)
from 7.8.0 to 7.9.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/brianvoe/gofakeit/releases">github.com/brianvoe/gofakeit/v7's
releases</a>.</em></p>
<blockquote>
<h2>ID Generator</h2>
<h1>New: <code>ID()</code> — Fast, Human-Readable Random Identifier</h1>
<p><em>(GoFakeIt v7.9.0)</em></p>
<p><code>gofakeit.ID()</code> is a new high-performance identifier
generator designed for <strong>speed</strong>,
<strong>readability</strong>, and <strong>practically zero collision
probability</strong>.</p>
<p>Unlike UUID v4 or XID, this generator is intentionally
<strong>random-first</strong>, not structure-based.<br />
Perfect for mock APIs, test data, fixtures, seed data, and temporary
identifiers.</p>
<hr />
<h2>Highlights</h2>
<ul>
<li><strong>Human readable alphabet</strong>, no confusing characters<br
/>
→ <code>23456789abcdefghjkmnpqrstuvwxyz</code> <em>(no 1, l, i or 0, o
to alleviate confusion)</em></li>
<li><strong>Fast</strong></li>
<li><strong>Memory Allocation</strong></li>
<li><strong>Generates from your rand source</strong></li>
<li><strong>Shorter than UUID</strong>, faster than XID, and requires no
coordination</li>
</ul>
<hr />
<h2>Example</h2>
<pre lang="go"><code>id := gofakeit.ID()
fmt.Println(id)
// → &quot;3t9qf4c92npxhw7bg6y0&quot;
</code></pre>
<hr />
<h2>Performance Benchmarks</h2>
<p>Measured on Go 1.25</p>
<table>
<thead>
<tr>
<th>Generator / Function</th>
<th>Benchmark Name</th>
<th>ops/sec</th>
<th>ns/op</th>
<th>B/op</th>
<th>allocs/op</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>gofakeit.ID()</code></td>
<td>BenchmarkID-10</td>
<td>31,383,146</td>
<td>37.8 ns</td>
<td>24</td>
<td>1</td>
</tr>
<tr>
<td><code>gofakeit.UUIDv4()</code></td>
<td>BenchmarkUUIDv4-10</td>
<td>22,131,577</td>
<td>53.8 ns</td>
<td>48</td>
<td>1</td>
</tr>
<tr>
<td><code>github.com/rs/xid</code></td>
<td>BenchmarkXID-10</td>
<td>16,190,817</td>
<td>74.2 ns</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td><code>github.com/google/uuid</code> (v4)</td>
<td>BenchmarkGoogleUUIDv4-10</td>
<td>3,098,770</td>
<td>386.1 ns</td>
<td>64</td>
<td>2</td>
</tr>
</tbody>
</table>
<p><strong>Takeaway:</strong> <code>gofakeit.ID()</code> is <strong>~2×
faster than XID</strong> and <strong>~10× faster than UUID v4</strong>,
while being shorter and human-readable.</p>
<hr />
<h2>Collision Probability (Randomness Math)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/93c1858df281da0d43482ac8186a21aafe60c75a"><code>93c1858</code></a>
password - improve memery allocation and minor increase in op speed</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/ce78392e670d1b5227ae7644977e99d3a7ed5ffc"><code>ce78392</code></a>
id - lookup updates and some other minor things</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/aba6d6fcd594f25201e305928de5ed454bc7ae43"><code>aba6d6f</code></a>
ids - moved uuid into ids file and add our own unique gofakeit id
generator</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/da6da65344eac1034f874fb6bac4664622b8c11d"><code>da6da65</code></a>
faker - pcg seed create 2 separate seeds using crypto</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/1e2c3fbb0173b6e51ff510eb9f8f1a32f047c35a"><code>1e2c3fb</code></a>
readme - added/organize ids</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/ae981a3966fb1423f9037bd0b2621eed1546c540"><code>ae981a3</code></a>
company - remove duplicate keyword/alias wording</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/969e3c7799804cfdb97c84680a27d31cdee52ecf"><code>969e3c7</code></a>
occupation - updated a few functions to favor job over emojijob</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/1ef7578f4711c08fc6fc81f675a5912d8b0c05da"><code>1ef7578</code></a>
occupation - updated a few functions to favor job over emojijob</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/a93e4a968e84cd3ae0ef63fa08645075bdfd4b37"><code>a93e4a9</code></a>
readme - minor update to remove unused functions</li>
<li><a
href="https://github.com/brianvoe/gofakeit/commit/f4eb855b56d393ba2ee69d0847b521c29e8c5a5b"><code>f4eb855</code></a>
text - added params back to sentence and paragraph to not break
builds</li>
<li>See full diff in <a
href="https://github.com/brianvoe/gofakeit/compare/v7.8.0...v7.9.0">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.8.0&new-version=7.9.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-10 14:05:56 +00:00
dependabot[bot] 4cbba17f10 ci: bump the github-actions group with 3 updates (#20703)
Bumps the github-actions group with 3 updates:
[step-security/harden-runner](https://github.com/step-security/harden-runner),
[tj-actions/changed-files](https://github.com/tj-actions/changed-files)
and
[Mattraks/delete-workflow-runs](https://github.com/mattraks/delete-workflow-runs).

Updates `step-security/harden-runner` from 2.13.1 to 2.13.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/step-security/harden-runner/releases">step-security/harden-runner's
releases</a>.</em></p>
<blockquote>
<h2>v2.13.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Fixed an issue where there was a limit of 512 allowed endpoints when
using block egress policy. This restriction has been removed, allowing
for an unlimited number of endpoints to be configured.</li>
<li>Harden Runner now automatically detects if the agent is already
pre-installed on a custom VM image used by a GitHub-hosted runner. When
detected, the action will skip reinstallation and use the existing
agent.</li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/step-security/harden-runner/compare/v2.13.1...v2.13.2">https://github.com/step-security/harden-runner/compare/v2.13.1...v2.13.2</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/step-security/harden-runner/commit/95d9a5deda9de15063e7595e9719c11c38c90ae2"><code>95d9a5d</code></a>
Merge pull request <a
href="https://redirect.github.com/step-security/harden-runner/issues/606">#606</a>
from step-security/rc-28</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/87e429d3fb470bcc827f338e5cce1155ff99c6eb"><code>87e429d</code></a>
Update limitations.md</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/ef891c3a30c3c15c2287ce04b33ec28b6d90a447"><code>ef891c3</code></a>
feat: add support for custom vm image</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/1fa8c8a8b1b523829fe596bfc665d2bc4c0ef835"><code>1fa8c8a</code></a>
update agent</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/92c522aaa6f53af082553dedc1596c80b71aba33"><code>92c522a</code></a>
Merge pull request <a
href="https://redirect.github.com/step-security/harden-runner/issues/593">#593</a>
from step-security/ak-readme-updates</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/4719ad5578c61961f4f70f833580278dea5544de"><code>4719ad5</code></a>
README updates</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/4fde639ab437b75bf4ecb52bbddb23ab0ac00259"><code>4fde639</code></a>
Merge pull request <a
href="https://redirect.github.com/step-security/harden-runner/issues/591">#591</a>
from eromosele-stepsecurity/Upd</li>
<li><a
href="https://github.com/step-security/harden-runner/commit/f682f2f2d06275b6ab30c2a973c1de2fa120e134"><code>f682f2f</code></a>
Update README.md</li>
<li>See full diff in <a
href="https://github.com/step-security/harden-runner/compare/f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a...95d9a5deda9de15063e7595e9719c11c38c90ae2">compare
view</a></li>
</ul>
</details>
<br />

Updates `tj-actions/changed-files` from
0ff001de0805038ff3f118de4875002200057732 to
70069877f29101175ed2b055d210fe8b1d54d7d7
<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/70069877f29101175ed2b055d210fe8b1d54d7d7"><code>7006987</code></a>
chore(deps): bump <code>@​octokit/rest</code> from 22.0.0 to 22.0.1 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2705">#2705</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/5df1bad3a527ede089326306d1296297ab0d58d2"><code>5df1bad</code></a>
chore(deps-dev): bump <code>@​types/node</code> from 24.9.2 to 24.10.0
(<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2707">#2707</a>)</li>
<li>See full diff in <a
href="https://github.com/tj-actions/changed-files/compare/0ff001de0805038ff3f118de4875002200057732...70069877f29101175ed2b055d210fe8b1d54d7d7">compare
view</a></li>
</ul>
</details>
<br />

Updates `Mattraks/delete-workflow-runs` from
86d29a75093353c4c509a876c176234037c2025b to
5bf9a1dac5c4d041c029f0a8370ddf0c5cb5aeb7
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Mattraks/delete-workflow-runs/commit/5bf9a1dac5c4d041c029f0a8370ddf0c5cb5aeb7"><code>5bf9a1d</code></a>
Bug Fixes</li>
<li><a
href="https://github.com/Mattraks/delete-workflow-runs/commit/63b223f231f2f5bbea217100ec6d29ab24faa7a1"><code>63b223f</code></a>
Supports daily retention keep a minimum number of runs per day</li>
<li>See full diff in <a
href="https://github.com/mattraks/delete-workflow-runs/compare/86d29a75093353c4c509a876c176234037c2025b...5bf9a1dac5c4d041c029f0a8370ddf0c5cb5aeb7">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-11-10 14:05:16 +00:00
dependabot[bot] 5587dbc622 chore: bump github.com/jedib0t/go-pretty/v6 from 6.6.7 to 6.7.1 (#20700)
Bumps
[github.com/jedib0t/go-pretty/v6](https://github.com/jedib0t/go-pretty)
from 6.6.7 to 6.7.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/jedib0t/go-pretty/releases">github.com/jedib0t/go-pretty/v6's
releases</a>.</em></p>
<blockquote>
<h2>v6.7.1</h2>
<h2>What's Changed</h2>
<ul>
<li>text: more unit-tests for escape seq parser by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/376">jedib0t/go-pretty#376</a></li>
<li>progress: speed-up unit-tests by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/377">jedib0t/go-pretty#377</a></li>
<li>table: profiling led performance fixes by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/378">jedib0t/go-pretty#378</a></li>
<li>progress: minor performance optimizations by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/379">jedib0t/go-pretty#379</a></li>
<li>text: transformer code quality fixes by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/380">jedib0t/go-pretty#380</a></li>
<li>documentation updates by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/381">jedib0t/go-pretty#381</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/jedib0t/go-pretty/compare/v6.7.0...v6.7.1">https://github.com/jedib0t/go-pretty/compare/v6.7.0...v6.7.1</a></p>
<h2>v6.7.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Only adjust terminal size when the output writer is stdout by <a
href="https://github.com/linzhp"><code>@​linzhp</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/375">jedib0t/go-pretty#375</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/linzhp"><code>@​linzhp</code></a> made
their first contribution in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/375">jedib0t/go-pretty#375</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/jedib0t/go-pretty/compare/v6.6.9...v6.7.0">https://github.com/jedib0t/go-pretty/compare/v6.6.9...v6.7.0</a></p>
<h2>v6.6.9</h2>
<h2>What's Changed</h2>
<ul>
<li>progress: option to skip auto-stop for trackers by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/373">jedib0t/go-pretty#373</a></li>
<li>feat: don't enable colors if <code>TERM</code> is set to
<code>dumb</code> by <a
href="https://github.com/G-Rath"><code>@​G-Rath</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/374">jedib0t/go-pretty#374</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/G-Rath"><code>@​G-Rath</code></a> made
their first contribution in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/374">jedib0t/go-pretty#374</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/jedib0t/go-pretty/compare/v6.6.8...v6.6.9">https://github.com/jedib0t/go-pretty/compare/v6.6.8...v6.6.9</a></p>
<h2>v6.6.8</h2>
<h2>What's Changed</h2>
<ul>
<li>OSC 8 hiperlink support by <a
href="https://github.com/houdini91"><code>@​houdini91</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/364">jedib0t/go-pretty#364</a></li>
<li>Add pac-man classic (chomp) and colored dominoes indeterminate
indicators by <a
href="https://github.com/mach6"><code>@​mach6</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/370">jedib0t/go-pretty#370</a></li>
<li>Experimental Style funcs for progress by <a
href="https://github.com/ptxmac"><code>@​ptxmac</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/369">jedib0t/go-pretty#369</a></li>
<li>progress demo tweaks by <a
href="https://github.com/jedib0t"><code>@​jedib0t</code></a> in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/371">jedib0t/go-pretty#371</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/houdini91"><code>@​houdini91</code></a>
made their first contribution in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/364">jedib0t/go-pretty#364</a></li>
<li><a href="https://github.com/mach6"><code>@​mach6</code></a> made
their first contribution in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/370">jedib0t/go-pretty#370</a></li>
<li><a href="https://github.com/ptxmac"><code>@​ptxmac</code></a> made
their first contribution in <a
href="https://redirect.github.com/jedib0t/go-pretty/pull/369">jedib0t/go-pretty#369</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/jedib0t/go-pretty/compare/v6.6.7...v6.6.8">https://github.com/jedib0t/go-pretty/compare/v6.6.7...v6.6.8</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/eb029c4a92f81289e19e5b1097e861444e6f9066"><code>eb029c4</code></a>
documentation updates (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/381">#381</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/02383244574fca4d1444ee6300e117333fdf517d"><code>0238324</code></a>
text: transformer code quality fixes (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/380">#380</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/a9ab184da9d7e349e04f8f0f56a3d6765db0a86d"><code>a9ab184</code></a>
progress: minor performance optimizations (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/379">#379</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/015f58dc8ebe02d513376bc12e5e3bf352ef5459"><code>015f58d</code></a>
table: profiling led minor performance fixes (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/378">#378</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/a3638c1fd954d6acea9c4686c2bd2cc2941c4ff6"><code>a3638c1</code></a>
progress: speed-up unit-tests (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/377">#377</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/d562c3e534b48d7e9a43369a02abe7c84c14eb47"><code>d562c3e</code></a>
text: more unit-tests for escape seq parser (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/376">#376</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/4d8d0737a68ec7338d9d3474faaeec635589fbaf"><code>4d8d073</code></a>
progress: adjust terminal size only when output is stdout (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/375">#375</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/b2249da83c58259eb9ba918f19dfd2ff43bf8ced"><code>b2249da</code></a>
text: don't enable colors if <code>TERM</code> is set to
<code>dumb</code> (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/374">#374</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/f8bbd121764f748b2d9cfae13ce042e61dd0811f"><code>f8bbd12</code></a>
progress: option to skip auto-stop for trackers (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/373">#373</a>)</li>
<li><a
href="https://github.com/jedib0t/go-pretty/commit/3c86af826bbe2883c693e0ff28b0fdd4fc3a9846"><code>3c86af8</code></a>
progress demo tweaks (<a
href="https://redirect.github.com/jedib0t/go-pretty/issues/371">#371</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/jedib0t/go-pretty/compare/v6.6.7...v6.7.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/jedib0t/go-pretty/v6&package-manager=go_modules&previous-version=6.6.7&new-version=6.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-11-10 14:04:56 +00:00
Cian Johnston 3819f33693 ci(.github/workflows/traiage.yaml): use create-task-action (#20673)
Updates the existing workflow to use the action defined in
coder/create-task-action.
2025-11-10 13:59:42 +00:00
Danny Kopping 0e21480794 chore: remove desktop-commander MCP server from dogfood template (#20694)
It's no longer required and conflicts with Claude Code's built-in tools
for filesystem operations.

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-10 15:40:54 +02:00
Paweł Banaszewski 991831b1dd chore: add API key ID to interceptions (#20513)
Adds APIKeyID to interceptions.
Needed for tracking API key usage with bridge.
fixes https://github.com/coder/coder/issues/20001
2025-11-10 13:46:41 +01:00
Cian Johnston 81c3375670 chore: update Go to 1.24.10 (#20684)
Signed-off-by: Danny Kopping <danny@coder.com>
Co-authored-by: Danny Kopping <danny@coder.com>
2025-11-10 09:09:44 +00:00
Danny Kopping b6d4ef2158 chore: conditionally disable aibridge in dogfood template (#20686)
Allow for conditionally disabling AI Bridge to investigate occasional
issues.
When AI Bridge is disabled, a static credential will be configured for
Claude.

AI Bridge is still enabled by default.

Signed-off-by: Danny Kopping <danny@coder.com>
2025-11-10 10:55:42 +02:00
Jacob Witt 1d1e1f92b0 docs: add OIDC documentation for Microsoft Entra ID user auth (#20202)
Propose Microsoft Entra ID OIDC Directions for Admin Documentation based
on my personal experience / setup.

Propose information on changing access URL in Tutorials -> FAQs

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: DevCats <chris@dualriver.com>
Co-authored-by: DevelopmentCats <christofer@coder.com>
2025-11-07 16:33:51 +05:00
Mathias Fredriksson ce04f6cc5d fix(coderd): remove deprecated AITaskSidebarApp column (#20680)
This column was no longer used in `v2.28` and the codersdk field
deprecated. Both can now be dropped in `v2.29`.

Closes coder/internal#974
2025-11-07 12:45:45 +02:00
Michael Suchacz 32e504cb2a chore: add cmux to dogfood template (#20681) 2025-11-07 10:41:30 +00:00
Mathias Fredriksson db76541522 test(codersdk/toolsdk): fix task status race for send/logs (#20682)
Fixes coder/internal#1111
2025-11-07 12:36:09 +02:00
Cian Johnston 7dc75637a1 fix(examples/templates/tasks-docker): support coder/claude-code 4.0.0 (#20420)
Relates to https://github.com/coder/internal/issues/1065
Essentially the same steps as https://github.com/coder/registry/pull/497
2025-11-06 16:12:21 +00:00
david-fraley b0f3effe2c docs: update release calendar for 2.28 release (#20666) 2025-11-06 15:29:18 +00:00
Cian Johnston 2cec1dbbfa chore: update coder/dogfood template to reference coder_task.prompt (#20416)
Relates to https://github.com/coder/internal/issues/1065

Updates the coder/dogfood template to reference new Task features in
provider version ~2.12.0~ 2.13.0:
- Adds a `coder_ai_task` resource and a `coder_task` data source
- Passes `coder_task.me.prompt` into Claude Code module
- Updates Claude Code module to 4.0.0 (ref:
https://github.com/coder/registry/pull/488)
- Removes "AI Prompt" parameter

Update: to avoid a cycle that only appears to occur when using a
`count`, leveraging a data source (ref:
https://github.com/coder/terraform-provider-coder/pull/460)
2025-11-06 15:00:56 +00:00
dependabot[bot] ab93943493 chore: bump github.com/opencontainers/runc from 1.2.3 to 1.2.8 (#20674)
Bumps
[github.com/opencontainers/runc](https://github.com/opencontainers/runc)
from 1.2.3 to 1.2.8.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/opencontainers/runc/releases">github.com/opencontainers/runc's
releases</a>.</em></p>
<blockquote>
<h2>runc v1.2.8 -- &quot;鳥籠の中に囚われた屈辱を&quot;</h2>
<blockquote>
<p>[!NOTE]
Some vendors were given a pre-release version of this release.
This public release includes two extra patches to fix regressions
discovered very late during the embargo period and were thus not
included in the pre-release versions. Please update to this version.</p>
</blockquote>
<p>This release contains fixes for three high-severity security
vulnerabilities in runc (<a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-9493-h29p-rfm2">CVE-2025-31133</a>,
<a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-qw9x-cqr3-wc7r">CVE-2025-52565</a>,
and
<a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-cgrx-mc8f-2prm">CVE-2025-52881</a>).
All three vulnerabilities ultimately allow (through
different methods) for full container breakouts by bypassing runc's
restrictions for writing to arbitrary <code>/proc</code> files.</p>
<h3>Security</h3>
<ul>
<li>
<p><a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-9493-h29p-rfm2">CVE-2025-31133</a>
exploits an issue with how masked paths are implemented in
runc. When masking files, runc will bind-mount the container's
<code>/dev/null</code>
inode on top of the file. However, if an attacker can replace
<code>/dev/null</code>
with a symlink to some other procfs file, runc will instead bind-mount
the
symlink target read-write. This issue affected all known runc
versions.</p>
</li>
<li>
<p><a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-qw9x-cqr3-wc7r">CVE-2025-52565</a>
is very similar in concept and application to
<a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-9493-h29p-rfm2">CVE-2025-31133</a>,
except that it exploits a flaw in <code>/dev/console</code>
bind-mounts. When creating the <code>/dev/console</code> bind-mount (to
<code>/dev/pts/$n</code>),
if an attacker replaces <code>/dev/pts/$n</code> with a symlink then
runc will
bind-mount the symlink target over <code>/dev/console</code>. This issue
affected all
versions of runc &gt;= 1.0.0-rc3.</p>
</li>
<li>
<p><a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-cgrx-mc8f-2prm">CVE-2025-52881</a>
is a more sophisticated variant of <a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-fh74-hm69-rqjw">CVE-2019-19921</a>,
which was a flaw that allowed an attacker to trick runc into writing the
LSM
process labels for a container process into a dummy tmpfs file and thus
not
apply the correct LSM labels to the container process. The mitigation we
applied for <a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-fh74-hm69-rqjw">CVE-2019-19921</a>
was fairly limited and effectively only caused
runc to verify that when we write LSM labels that those labels are
actual
procfs files. This issue affects all known runc versions.</p>
</li>
</ul>
<h3>Static Linking Notices</h3>
<p>The <code>runc</code> binary distributed with this release are
<em>statically linked</em> with
the following <a
href="https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html">GNU
LGPL-2.1</a> licensed libraries, with <code>runc</code> acting
as a &quot;work that uses the Library&quot;:</p>
<ul>
<li><a href="https://github.com/seccomp/libseccomp">libseccomp</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/opencontainers/runc/blob/v1.2.8/CHANGELOG.md">github.com/opencontainers/runc's
changelog</a>.</em></p>
<blockquote>
<h2>[1.2.8] - 2025-11-05</h2>
<blockquote>
<p>鳥籠の中に囚われた屈辱を</p>
</blockquote>
<h3>Security</h3>
<p>This release includes fixes for the following high-severity security
issues:</p>
<ul>
<li>
<p><a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-9493-h29p-rfm2">CVE-2025-31133</a>
exploits an issue with how masked paths are implemented in
runc. When masking files, runc will bind-mount the container's
<code>/dev/null</code>
inode on top of the file. However, if an attacker can replace
<code>/dev/null</code>
with a symlink to some other procfs file, runc will instead bind-mount
the
symlink target read-write. This issue affected all known runc
versions.</p>
</li>
<li>
<p><a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-qw9x-cqr3-wc7r">CVE-2025-52565</a>
is very similar in concept and application to
<a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-9493-h29p-rfm2">CVE-2025-31133</a>,
except that it exploits a flaw in <code>/dev/console</code>
bind-mounts. When creating the <code>/dev/console</code> bind-mount (to
<code>/dev/pts/$n</code>),
if an attacker replaces <code>/dev/pts/$n</code> with a symlink then
runc will
bind-mount the symlink target over <code>/dev/console</code>. This issue
affected all
versions of runc &gt;= 1.0.0-rc3.</p>
</li>
<li>
<p><a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-cgrx-mc8f-2prm">CVE-2025-52881</a>
is a more sophisticated variant of <a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-fh74-hm69-rqjw">CVE-2019-19921</a>,
which was a flaw that allowed an attacker to trick runc into writing the
LSM
process labels for a container process into a dummy tmpfs file and thus
not
apply the correct LSM labels to the container process. The mitigation we
applied for <a
href="https://github.com/opencontainers/runc/security/advisories/GHSA-fh74-hm69-rqjw">CVE-2019-19921</a>
was fairly limited and effectively only caused
runc to verify that when we write LSM labels that those labels are
actual
procfs files. This issue affects all known runc versions.</p>
</li>
</ul>
<h2>[1.2.7] - 2025-09-05</h2>
<blockquote>
<p>さんをつけろよデコ助野郎!</p>
</blockquote>
<h3>Fixed</h3>
<ul>
<li>Removed preemptive &quot;full access to cgroups&quot; warning when
calling <code>runc pause</code> or <code>runc unpause</code> as an
unprivileged user without
<code>--systemd-cgroups</code>. Now the warning is only emitted if an
actual permission
error was encountered. (<a
href="https://redirect.github.com/opencontainers/runc/issues/4709">#4709</a>,
<a
href="https://redirect.github.com/opencontainers/runc/issues/4720">#4720</a>)</li>
<li>Add time namespace to container config after checkpoint/restore.
CRIU since
version 3.14 uses a time namespace for checkpoint/restore, however it
was
not joining the time namespace in runc. (<a
href="https://redirect.github.com/opencontainers/runc/issues/4696">#4696</a>,
<a
href="https://redirect.github.com/opencontainers/runc/issues/4714">#4714</a>)</li>
<li>Container processes will no longer inherit the CPU affinity of runc
by
default. Instead, the default CPU affinity of container processes will
be
the largest set of CPUs permitted by the container's cpuset cgroup and
any
other system restrictions (such as isolated CPUs). (<a
href="https://redirect.github.com/opencontainers/runc/issues/4041">#4041</a>,
<a
href="https://redirect.github.com/opencontainers/runc/issues/4815">#4815</a>,
<a
href="https://redirect.github.com/opencontainers/runc/issues/4858">#4858</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/opencontainers/runc/commit/eeb7e6024f9ee43876301b1d23c353384fa6dcdd"><code>eeb7e60</code></a>
VERSION: release v1.2.8</li>
<li><a
href="https://github.com/opencontainers/runc/commit/cdee962c391af84a922252c283bd065e5cabb34b"><code>cdee962</code></a>
merge private security patches into ghsa-release-1.2.8</li>
<li><a
href="https://github.com/opencontainers/runc/commit/b4cb2f5436a1110a1de4eec7335a791d2b30a868"><code>b4cb2f5</code></a>
rootfs: re-allow dangling symlinks in mount targets</li>
<li><a
href="https://github.com/opencontainers/runc/commit/ee56b8571cc81d41f85b069671bb6d33fd235cf1"><code>ee56b85</code></a>
openat2: improve resilience on busy systems</li>
<li><a
href="https://github.com/opencontainers/runc/commit/2462b68fa2d6618480e6a4f615661ee6e762d13a"><code>2462b68</code></a>
Merge pull request <a
href="https://redirect.github.com/opencontainers/runc/issues/4943">#4943</a>
from lifubang/backport-1.2-4934-4937</li>
<li><a
href="https://github.com/opencontainers/runc/commit/99e41a58f7a51cf1b6caa5bed58ffbe615193523"><code>99e41a5</code></a>
ci: only run lint-extra job on PRs to main</li>
<li><a
href="https://github.com/opencontainers/runc/commit/f2a1c986629e82cffb3b7c01eee68405894f4783"><code>f2a1c98</code></a>
CI: remove deprecated lima-vm/lima-actions/ssh</li>
<li><a
href="https://github.com/opencontainers/runc/commit/8f901856f96126285585e7343d7bc600013798fc"><code>8f90185</code></a>
selinux: use safe procfs API for labels</li>
<li><a
href="https://github.com/opencontainers/runc/commit/948d6e9dbece33da25886f18c97a128c347e95ff"><code>948d6e9</code></a>
rootfs: switch to fd-based handling of mountpoint targets</li>
<li><a
href="https://github.com/opencontainers/runc/commit/7aa42ade85d575294cf778b21edbd53c0171a3d4"><code>7aa42ad</code></a>
libct: align param type for mountCgroupV1/V2 functions</li>
<li>Additional commits viewable in <a
href="https://github.com/opencontainers/runc/compare/v1.2.3...v1.2.8">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/opencontainers/runc&package-manager=go_modules&previous-version=1.2.3&new-version=1.2.8)](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-11-05 17:01:21 +00:00
Cian Johnston 34f6e72879 feat(coderd): add lookup task by name in httpmw.TaskParam (#20647)
* Adds a `GetTaskByOwnerIDAndName` query
* Updates `httpmw.TaskParam` to fall back to task name if no task by
UUID found.
* Updates the `TaskByIdentifier` used in `cli/` to use direct lookup instead of searching.
2025-11-05 14:28:34 +00:00
Mathias Fredriksson 46b2f3df8e fix(cli): allow disabling debug listening ports for agent (#20671)
A customer reported unexpected port allocation in their workspace. When
looking into it I noticed we always hijack these ports and there is no 
way to disable them entirely.

This change allows the servers to be disabled by setting them to the
empty string. Previously they would still listen on ephemeral ports.

```console
❯ coder agent --help | grep -E '211[2-3]|6060'
      --debug-address string, $CODER_AGENT_DEBUG_ADDRESS (default: 127.0.0.1:2113)
      --pprof-address string, $CODER_AGENT_PPROF_ADDRESS (default: 127.0.0.1:6060)
      --prometheus-address string, $CODER_AGENT_PROMETHEUS_ADDRESS (default: 127.0.0.1:2112)
```

There are now two ways to disable, either via CLI or env variables:

```console
# Flags.
coder agent --debug-address= --pprof-address= --prometheus-address=

# Environment variables.
export CODER_AGENT_DEBUG_ADDRESS=
export CODER_AGENT_PPROF_ADDRESS=
export CODER_AGENT_PROMETHEUS_ADDRESS=
coder agent
```
2025-11-05 14:22:24 +02:00
Mathias Fredriksson dec2c4c4e2 fix(site): fix task table links in Safari (#20663)
This change makes the TableRow clickable rather than having an
absolutely positioned RouterLink. In Safari the entire table was broken
because all links spanned across the whole table, and the bottom most
row shadowed all others, resulting in only the bottom row being
highlighted and all rows leading to the bottom most task.
2025-11-04 14:16:43 +00:00
Dean Sheather b3f651d62f chore: change managed agent limit (#20540) 2025-11-05 00:46:27 +11:00
Mathias Fredriksson daad93967a fix(coderd): fix template ai task check error message (#20651)
Create task was still mentioning magic prompt parameter when checking
template task validity. This change updates it to only mention validity
of `coder_ai_task` resource.
2025-11-03 12:54:43 +00:00
dependabot[bot] afd7fc8687 chore: bump rust from e4ae8ab to af95fd1 in /dogfood/coder (#20657)
Bumps rust from `e4ae8ab` to `af95fd1`.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rust&package-manager=docker&previous-version=slim&new-version=slim)](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-03 12:26:16 +00:00
dependabot[bot] 4fa5e6ee3b chore: bump ubuntu from 4e0171b to 0950623 in /dogfood/coder (#20658)
Bumps ubuntu from `4e0171b` to `0950623`.


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ubuntu&package-manager=docker&previous-version=jammy&new-version=jammy)](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-03 12:26:01 +00:00
dependabot[bot] a34897817f ci: bump the github-actions group with 6 updates (#20656)
Bumps the github-actions group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [crate-ci/typos](https://github.com/crate-ci/typos) | `1.38.1` |
`1.39.0` |
| [chromaui/action](https://github.com/chromaui/action) | `13.3.2` |
`13.3.3` |
| [fluxcd/flux2](https://github.com/fluxcd/flux2) | `2.7.2` | `2.7.3` |
|
[tj-actions/changed-files](https://github.com/tj-actions/changed-files)
| `dbf178ceecb9304128c8e0648591d71208c6e2c9` |
`0ff001de0805038ff3f118de4875002200057732` |
| [github/codeql-action](https://github.com/github/codeql-action) |
`4.31.0` | `4.31.2` |
|
[Mattraks/delete-workflow-runs](https://github.com/mattraks/delete-workflow-runs)
| `ab482449ba468316e9a8801e092d0405715c5e6d` |
`86d29a75093353c4c509a876c176234037c2025b` |

Updates `crate-ci/typos` from 1.38.1 to 1.39.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.39.0</h2>
<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>
</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.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>
<ul>
<li>Don't correct <code>typ</code></li>
<li>Consistently error on unused config fields</li>
</ul>
<h2>[1.37.3] - 2025-10-06</h2>
<h3>Fixes</h3>
<ul>
<li>Don't correct <code>PN</code> for <code>bitbake</code> file
types</li>
</ul>
<h2>[1.37.2] - 2025-10-03</h2>
<h3>Fixes</h3>
<ul>
<li>Don't suggest <code>diagnostic</code> for <code>diagnotics</code>,
preferring <code>diagnostics</code></li>
</ul>
<h2>[1.37.1] - 2025-10-01</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/crate-ci/typos/commit/07d900b8fa1097806b8adb6391b0d3e0ac2fdea7"><code>07d900b</code></a>
chore: Release</li>
<li><a
href="https://github.com/crate-ci/typos/commit/fcce1f892d5149dd02bcdce2cabdbfd58609fdf0"><code>fcce1f8</code></a>
chore: Release</li>
<li><a
href="https://github.com/crate-ci/typos/commit/85692fd91b604adb2caa6c9852a6693c84c330e0"><code>85692fd</code></a>
docs: Update changelog</li>
<li><a
href="https://github.com/crate-ci/typos/commit/da7527cc3513111180ccc1f1635559fcb13c03c2"><code>da7527c</code></a>
Merge pull request <a
href="https://redirect.github.com/crate-ci/typos/issues/1406">#1406</a>
from epage/oct</li>
<li><a
href="https://github.com/crate-ci/typos/commit/9046b5b2e97e5b58560fc4d6ca00bb1629b5272f"><code>9046b5b</code></a>
feat(dict): October additions</li>
<li><a
href="https://github.com/crate-ci/typos/commit/9a86c0a0c033d31643ca72c09323c8ea4ad8154c"><code>9a86c0a</code></a>
docs: Update screenshot</li>
<li>See full diff in <a
href="https://github.com/crate-ci/typos/compare/80c8a4945eec0f6d464eaf9e65ed98ef085283d1...07d900b8fa1097806b8adb6391b0d3e0ac2fdea7">compare
view</a></li>
</ul>
</details>
<br />

Updates `chromaui/action` from 13.3.2 to 13.3.3
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/chromaui/action/commit/ac86f2ff0a458ffbce7b40698abd44c0fa34d4b6"><code>ac86f2f</code></a>
v13.3.3</li>
<li>See full diff in <a
href="https://github.com/chromaui/action/compare/bc2d84ad2b60813a67d995c5582d696104a19383...ac86f2ff0a458ffbce7b40698abd44c0fa34d4b6">compare
view</a></li>
</ul>
</details>
<br />

Updates `fluxcd/flux2` from 2.7.2 to 2.7.3
<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.3</h2>
<h2>Highlights</h2>
<p>Flux v2.7.3 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>Restore SOCKS5 proxy support in all controllers</li>
<li>Fix status reporting of HelmReleases with
<code>RetryOnFailure</code> strategy</li>
<li>Automated retries for ImagePolicies when no image tags are found in
the database</li>
<li>Fix alerting for Telegram's <code>message_thread_id</code></li>
<li>Allow running kustomize-controller and helm-controller on the same
loopback interface as source-watcher</li>
</ul>
<p>⚠️ Note that signature verification for OCI artifacts in
source-controller is not compatible with Cosign v3. 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.3/CHANGELOG.md">v1.7.3</a></li>
<li>kustomize-controller <a
href="https://github.com/fluxcd/kustomize-controller/blob/v1.7.2/CHANGELOG.md">v1.7.2</a></li>
<li>notification-controller <a
href="https://github.com/fluxcd/notification-controller/blob/v1.7.4/CHANGELOG.md">v1.7.4</a></li>
<li>helm-controller <a
href="https://github.com/fluxcd/helm-controller/blob/v1.4.3/CHANGELOG.md">v1.4.3</a></li>
<li>image-reflector-controller <a
href="https://github.com/fluxcd/image-reflector-controller/blob/v1.0.3/CHANGELOG.md">v1.0.3</a></li>
<li>image-automation-controller <a
href="https://github.com/fluxcd/image-automation-controller/blob/v1.0.3/CHANGELOG.md">v1.0.3</a></li>
</ul>
<h2>CLI changelog</h2>
<ul>
<li>[release/v2.7.x] Pin cosign to v2.6.1 by <a
href="https://github.com/fluxcdbot"><code>@​fluxcdbot</code></a> in <a
href="https://redirect.github.com/fluxcd/flux2/pull/5595">fluxcd/flux2#5595</a></li>
<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/5605">fluxcd/flux2#5605</a></li>
<li>[release/v2.7.x] fix: return accepted values for flags when calling
Values.Type() by <a
href="https://github.com/fluxcdbot"><code>@​fluxcdbot</code></a> in <a
href="https://redirect.github.com/fluxcd/flux2/pull/5606">fluxcd/flux2#5606</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/fluxcd/flux2/compare/v2.7.2...v2.7.3">https://github.com/fluxcd/flux2/compare/v2.7.2...v2.7.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/fluxcd/flux2/commit/b6e76ca2534f76dcb8dd94fb057cdfa923c3b641"><code>b6e76ca</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5606">#5606</a>
from fluxcd/backport-5602-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/e084250147016da777198245790c42a6d45446f0"><code>e084250</code></a>
fix: return supported values for flags when calling Values.Type()</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/c3bc3d59b308f0c44285b2629c51632d88fe5951"><code>c3bc3d5</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5605">#5605</a>
from fluxcd/backport-5603-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/1295ba285e98bd6ee1fa2932ec0f7e4052189b9b"><code>1295ba2</code></a>
Fix bootstrap e2e test for image policy</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/41ebc0e0f93f9bf1490c8cb1b5a6f6c41646c61a"><code>41ebc0e</code></a>
Update toolkit components</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/67d2fb09a47ee2b9b454dc85eda8971edff57969"><code>67d2fb0</code></a>
Merge pull request <a
href="https://redirect.github.com/fluxcd/flux2/issues/5595">#5595</a>
from fluxcd/backport-5594-to-release/v2.7.x</li>
<li><a
href="https://github.com/fluxcd/flux2/commit/888e8a9affc6da3fb934efc9e3ff2f32fa06fd57"><code>888e8a9</code></a>
Pin cosign to v2.6.1</li>
<li>See full diff in <a
href="https://github.com/fluxcd/flux2/compare/4a15fa6a023259353ef750acf1c98fe88407d4d0...b6e76ca2534f76dcb8dd94fb057cdfa923c3b641">compare
view</a></li>
</ul>
</details>
<br />

Updates `tj-actions/changed-files` from
dbf178ceecb9304128c8e0648591d71208c6e2c9 to
0ff001de0805038ff3f118de4875002200057732
<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/0ff001de0805038ff3f118de4875002200057732"><code>0ff001d</code></a>
chore(deps-dev): bump ts-jest from 29.4.4 to 29.4.5 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2688">#2688</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/52b808ab08e9b9ef06f5af6d3fea1d639da110e0"><code>52b808a</code></a>
chore(deps-dev): bump <code>@​types/micromatch</code> from 4.0.9 to
4.0.10 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2699">#2699</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/d6388b78bdbccf5326651d609098231d6e08f14a"><code>d6388b7</code></a>
chore(deps): bump actions/download-artifact from 5.0.0 to 6.0.0 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2697">#2697</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/cf5e80aa29743eb7ed7921b82bf9209a55d09fcd"><code>cf5e80a</code></a>
chore(deps): bump actions/upload-artifact from 4.6.2 to 5.0.0 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2698">#2698</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/cff45432265e1bbeebeaf038878246c6749a68b5"><code>cff4543</code></a>
chore(deps-dev): bump <code>@​types/node</code> from 24.9.1 to 24.9.2
(<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2700">#2700</a>)</li>
<li><a
href="https://github.com/tj-actions/changed-files/commit/9dc1b5f80eeefcffeb145deb4dcc0def0d8cae70"><code>9dc1b5f</code></a>
chore(deps): bump github/codeql-action from 4.30.9 to 4.31.2 (<a
href="https://redirect.github.com/tj-actions/changed-files/issues/2702">#2702</a>)</li>
<li>See full diff in <a
href="https://github.com/tj-actions/changed-files/compare/dbf178ceecb9304128c8e0648591d71208c6e2c9...0ff001de0805038ff3f118de4875002200057732">compare
view</a></li>
</ul>
</details>
<br />

Updates `github/codeql-action` from 4.31.0 to 4.31.2
<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.2</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.2 - 30 Oct 2025</h2>
<p>No user facing changes.</p>
<p>See the full <a
href="https://github.com/github/codeql-action/blob/v4.31.2/CHANGELOG.md">CHANGELOG.md</a>
for more information.</p>
<h2>v4.31.1</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.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>
<p>See the full <a
href="https://github.com/github/codeql-action/blob/v4.31.1/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.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>
<h2>3.30.6 - 02 Oct 2025</h2>
<ul>
<li>Update default CodeQL bundle version to 2.23.2. <a
href="https://redirect.github.com/github/codeql-action/pull/3168">#3168</a></li>
</ul>
<h2>3.30.5 - 26 Sep 2025</h2>
<ul>
<li>We fixed a bug that was introduced in <code>3.30.4</code> with
<code>upload-sarif</code> which resulted in files without a
<code>.sarif</code> extension not getting uploaded. <a
href="https://redirect.github.com/github/codeql-action/pull/3160">#3160</a></li>
</ul>
<h2>3.30.4 - 25 Sep 2025</h2>
<ul>
<li>We have improved the CodeQL Action's ability to validate that the
workflow it is used in does not use different versions of the CodeQL
Action for different workflow steps. Mixing different versions of the
CodeQL Action in the same workflow is unsupported and can lead to
unpredictable results. A warning will now be emitted from the
<code>codeql-action/init</code> step if different versions of the CodeQL
Action are detected in the workflow file. Additionally, an error will
now be thrown by the other CodeQL Action steps if they load a
configuration file that was generated by a different version of the
<code>codeql-action/init</code> step. <a
href="https://redirect.github.com/github/codeql-action/pull/3099">#3099</a>
and <a
href="https://redirect.github.com/github/codeql-action/pull/3100">#3100</a></li>
<li>We added support for reducing the size of dependency caches for Java
analyses, which will reduce cache usage and speed up workflows. This
will be enabled automatically at a later time. <a
href="https://redirect.github.com/github/codeql-action/pull/3107">#3107</a></li>
<li>You can now run the latest CodeQL nightly bundle by passing
<code>tools: nightly</code> to the <code>init</code> action. In general,
the nightly bundle is unstable and we only recommend running it when
directed by GitHub staff. <a
href="https://redirect.github.com/github/codeql-action/pull/3130">#3130</a></li>
<li>Update default CodeQL bundle version to 2.23.1. <a
href="https://redirect.github.com/github/codeql-action/pull/3118">#3118</a></li>
</ul>
<h2>3.30.3 - 10 Sep 2025</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/github/codeql-action/commit/0499de31b99561a6d14a36a5f662c2a54f91beee"><code>0499de3</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3261">#3261</a>
from github/henrymercer/setup-python</li>
<li><a
href="https://github.com/github/codeql-action/commit/3b96745d2bb2af9f01a0c9a19f4ffd034ae37879"><code>3b96745</code></a>
Set up Python in mergeback workflow</li>
<li><a
href="https://github.com/github/codeql-action/commit/8a06050a8c0348fb4738f28e0cfbb6727cf054ce"><code>8a06050</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3259">#3259</a>
from github/update-v4.31.2-9576b5cbe</li>
<li><a
href="https://github.com/github/codeql-action/commit/752a642cb25304f2aaae33cfcc3911673bf65aca"><code>752a642</code></a>
Update changelog for v4.31.2</li>
<li><a
href="https://github.com/github/codeql-action/commit/9576b5cbe818ddefe4e1b444017536fe40b9ab2d"><code>9576b5c</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3258">#3258</a>
from github/mbg/enablement-errors/case-insensitive</li>
<li><a
href="https://github.com/github/codeql-action/commit/cc8843728c8296d35175b82c7f1bb3748290764a"><code>cc88437</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3257">#3257</a>
from github/henrymercer/ubuntu-slim</li>
<li><a
href="https://github.com/github/codeql-action/commit/f0e9bf07f44488f7e3adf5ff01d04e6392b60b3b"><code>f0e9bf0</code></a>
Make <code>isEnablementError</code> case-insensitive</li>
<li><a
href="https://github.com/github/codeql-action/commit/2a3599c52055e7a5443d3fef8981a4d543586dde"><code>2a3599c</code></a>
Run lightweight workflows on <code>ubuntu-slim</code></li>
<li><a
href="https://github.com/github/codeql-action/commit/514ff4d116ef04d9ffc8adb3da5abb07961cb990"><code>514ff4d</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3256">#3256</a>
from github/henrymercer/resolve-bad-merge</li>
<li><a
href="https://github.com/github/codeql-action/commit/aab1c2f9318aa4b88e7532de10fe02ac860d5ab8"><code>aab1c2f</code></a>
Merge pull request <a
href="https://redirect.github.com/github/codeql-action/issues/3253">#3253</a>
from github/mergeback/v4.31.1-to-main-5fe9434c</li>
<li>Additional commits viewable in <a
href="https://github.com/github/codeql-action/compare/4e94bd11f71e507f7f87df81788dff88d1dacbfb...0499de31b99561a6d14a36a5f662c2a54f91beee">compare
view</a></li>
</ul>
</details>
<br />

Updates `Mattraks/delete-workflow-runs` from
ab482449ba468316e9a8801e092d0405715c5e6d to
86d29a75093353c4c509a876c176234037c2025b
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Mattraks/delete-workflow-runs/commit/86d29a75093353c4c509a876c176234037c2025b"><code>86d29a7</code></a>
Update deprecated <code>@​octokit/rest</code> library call methods</li>
<li>See full diff in <a
href="https://github.com/mattraks/delete-workflow-runs/compare/ab482449ba468316e9a8801e092d0405715c5e6d...86d29a75093353c4c509a876c176234037c2025b">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-11-03 12:19:52 +00:00
dependabot[bot] 9c22ae847e chore: bump github.com/anthropics/anthropic-sdk-go from 1.13.0 to 1.16.0 (#20654)
Bumps
[github.com/anthropics/anthropic-sdk-go](https://github.com/anthropics/anthropic-sdk-go)
from 1.13.0 to 1.16.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.16.0</h2>
<h2>1.16.0 (2025-10-29)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.15.0...v1.16.0">v1.15.0...v1.16.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add ability to clear thinking in context
management (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/6082754e9b6a04570a93efdb5339853c71f1fe94">6082754</a>)</li>
</ul>
<h2>v1.15.0</h2>
<h2>1.15.0 (2025-10-28)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.14.0...v1.15.0">v1.14.0...v1.15.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> adding support for agent skills (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/5660b5252a4de07f3343c9089b148b16cda794d4">5660b52</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>api:</strong> mark older sonnet models as deprecated (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/f13c5bd18ebb169c59913985537ca025634ef7eb">f13c5bd</a>)</li>
</ul>
<h2>v1.14.0</h2>
<h2>1.14.0 (2025-10-15)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.13.0...v1.14.0">v1.13.0...v1.14.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> manual updates (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/3eac8aaee0dbb3f4a5e30b039d60503614365a82">3eac8aa</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>client:</strong> add context-management-2025-06-27 beta
header (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/eeba6fa95ca9eedf16897b413950fc5f80d0d8cb">eeba6fa</a>)</li>
<li><strong>client:</strong> add
model-context-window-exceeded-2025-08-26 beta header (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/7d5a37d895b769739d23b6e91f6c0a806cade710">7d5a37d</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.16.0 (2025-10-29)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.15.0...v1.16.0">v1.15.0...v1.16.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> add ability to clear thinking in context
management (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/6082754e9b6a04570a93efdb5339853c71f1fe94">6082754</a>)</li>
</ul>
<h2>1.15.0 (2025-10-28)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.14.0...v1.15.0">v1.14.0...v1.15.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> adding support for agent skills (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/5660b5252a4de07f3343c9089b148b16cda794d4">5660b52</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>api:</strong> mark older sonnet models as deprecated (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/f13c5bd18ebb169c59913985537ca025634ef7eb">f13c5bd</a>)</li>
</ul>
<h2>1.14.0 (2025-10-15)</h2>
<p>Full Changelog: <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.13.0...v1.14.0">v1.13.0...v1.14.0</a></p>
<h3>Features</h3>
<ul>
<li><strong>api:</strong> manual updates (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/3eac8aaee0dbb3f4a5e30b039d60503614365a82">3eac8aa</a>)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><strong>client:</strong> add context-management-2025-06-27 beta
header (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/eeba6fa95ca9eedf16897b413950fc5f80d0d8cb">eeba6fa</a>)</li>
<li><strong>client:</strong> add
model-context-window-exceeded-2025-08-26 beta header (<a
href="https://github.com/anthropics/anthropic-sdk-go/commit/7d5a37d895b769739d23b6e91f6c0a806cade710">7d5a37d</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/3a0275d6034e4eda9fbc8366d8a5d8b3a462b4cc"><code>3a0275d</code></a>
Merge pull request <a
href="https://redirect.github.com/anthropics/anthropic-sdk-go/issues/247">#247</a>
from anthropics/release-please--branches--main--chang...</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/368ce719173c195f56fc6088715df89a4160a062"><code>368ce71</code></a>
release: 1.16.0</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/6082754e9b6a04570a93efdb5339853c71f1fe94"><code>6082754</code></a>
feat(api): add ability to clear thinking in context management</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/b2bfcccf501a8aabe14b961284f8721faa15b7a7"><code>b2bfccc</code></a>
Merge pull request <a
href="https://redirect.github.com/anthropics/anthropic-sdk-go/issues/244">#244</a>
from anthropics/release-please--branches--main--chang...</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/bf69f4bd3c217a7e1fd1d4e1eadbaae04540c218"><code>bf69f4b</code></a>
release: 1.15.0</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/f13c5bd18ebb169c59913985537ca025634ef7eb"><code>f13c5bd</code></a>
chore(api): mark older sonnet models as deprecated</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/5660b5252a4de07f3343c9089b148b16cda794d4"><code>5660b52</code></a>
feat(api): adding support for agent skills</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/7fbe034f74544414475ed46a5dce5b6388524dbf"><code>7fbe034</code></a>
release: 1.14.0</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/e678457abbbddbd241b3f6a8129de23580adb1e9"><code>e678457</code></a>
feat(api): manual updates</li>
<li><a
href="https://github.com/anthropics/anthropic-sdk-go/commit/87e262b1b84a1ce9a0b8315fa6583e6cde9fba83"><code>87e262b</code></a>
codegen metadata</li>
<li>Additional commits viewable in <a
href="https://github.com/anthropics/anthropic-sdk-go/compare/v1.13.0...v1.16.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.13.0&new-version=1.16.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-03 12:15:28 +00:00
dependabot[bot] 891274838e chore: bump google.golang.org/api from 0.253.0 to 0.254.0 (#20653)
Bumps
[google.golang.org/api](https://github.com/googleapis/google-api-go-client)
from 0.253.0 to 0.254.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.254.0</h2>
<h2><a
href="https://github.com/googleapis/google-api-go-client/compare/v0.253.0...v0.254.0">0.254.0</a>
(2025-10-28)</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/3348">#3348</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/8e2becc10cbfe6a5f2c9ad147730f4271c364417">8e2becc</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3350">#3350</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/9e07cd04a1bc6d229520b666a3f5d00dfb930d4c">9e07cd0</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3351">#3351</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/470f33c2321d0b6e81b1b55cbc2640edad5fc848">470f33c</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3352">#3352</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/cff2ae692ea1ed74b7b280196b4b8391005e7f76">cff2ae6</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3354">#3354</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/6b3a07f3cd5d3163ac3453bdb970bde23a57a734">6b3a07f</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3355">#3355</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/4c613b616c15fd2597fc898a8bb07bef890a85a1">4c613b6</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.253.0...v0.254.0">0.254.0</a>
(2025-10-28)</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/3348">#3348</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/8e2becc10cbfe6a5f2c9ad147730f4271c364417">8e2becc</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3350">#3350</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/9e07cd04a1bc6d229520b666a3f5d00dfb930d4c">9e07cd0</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3351">#3351</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/470f33c2321d0b6e81b1b55cbc2640edad5fc848">470f33c</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3352">#3352</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/cff2ae692ea1ed74b7b280196b4b8391005e7f76">cff2ae6</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3354">#3354</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/6b3a07f3cd5d3163ac3453bdb970bde23a57a734">6b3a07f</a>)</li>
<li><strong>all:</strong> Auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3355">#3355</a>)
(<a
href="https://github.com/googleapis/google-api-go-client/commit/4c613b616c15fd2597fc898a8bb07bef890a85a1">4c613b6</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/476426f2d0efaef35ef067a0edb7323d8d8b2f76"><code>476426f</code></a>
chore(main): release 0.254.0 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3349">#3349</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/4c613b616c15fd2597fc898a8bb07bef890a85a1"><code>4c613b6</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3355">#3355</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/33b87ade12194cdeaad399a755d985a3c0992442"><code>33b87ad</code></a>
chore(all): update all to 3a174f9 (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3353">#3353</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/6b3a07f3cd5d3163ac3453bdb970bde23a57a734"><code>6b3a07f</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3354">#3354</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/cff2ae692ea1ed74b7b280196b4b8391005e7f76"><code>cff2ae6</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3352">#3352</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/470f33c2321d0b6e81b1b55cbc2640edad5fc848"><code>470f33c</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3351">#3351</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/9e07cd04a1bc6d229520b666a3f5d00dfb930d4c"><code>9e07cd0</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3350">#3350</a>)</li>
<li><a
href="https://github.com/googleapis/google-api-go-client/commit/8e2becc10cbfe6a5f2c9ad147730f4271c364417"><code>8e2becc</code></a>
feat(all): auto-regenerate discovery clients (<a
href="https://redirect.github.com/googleapis/google-api-go-client/issues/3348">#3348</a>)</li>
<li>See full diff in <a
href="https://github.com/googleapis/google-api-go-client/compare/v0.253.0...v0.254.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.253.0&new-version=0.254.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-03 12:15:18 +00:00
Mathias Fredriksson a6b0eae38d refactor(coderd): drop sidebar app constraint and simplify provisionerdserver for tasks (#20591)
Updates coder/internal#973
Updates coder/internal#974
2025-11-03 13:46:38 +02:00
Cian Johnston 1961252918 chore(coderd/provisionerdserver): address flake in TestServer_ExpirePrebuildsSessionToken (#20648)
Addresses a flake seen locally by @mafredri:

```
panic: interface conversion: proto.isAcquiredJob_Type is nil, not *proto.AcquiredJob_WorkspaceBuild_ [recovered]
        panic: interface conversion: proto.isAcquiredJob_Type is nil, not *proto.AcquiredJob_WorkspaceBuild_

goroutine 77 [running]:
testing.tRunner.func1.2({0x35ba440, 0xc000f15620})
        /usr/local/go/src/testing/testing.go:1734 +0x21c
testing.tRunner.func1()
        /usr/local/go/src/testing/testing.go:1737 +0x35e
panic({0x35ba440?, 0xc000f15620?})
        /usr/local/go/src/runtime/panic.go:792 +0x132
github.com/coder/coder/v2/coderd/provisionerdserver_test.TestServer_ExpirePrebuildsSessionToken(0xc00010d500)                                 /home/coder/coder/coderd/provisionerdserver/provisionerdserver_test.go:4128 +0xc4b
testing.tRunner(0xc00010d500, 0x4bd8450)
        /usr/local/go/src/testing/testing.go:1792 +0xf4
created by testing.(*T).Run in goroutine 1
        /usr/local/go/src/testing/testing.go:1851 +0x413
FAIL    github.com/coder/coder/v2/coderd/provisionerdserver     20.830s
FAIL
```

It's unclear why this would happen in the first place.
2025-11-03 11:39:02 +00:00
Cian Johnston 11f24119c5 chore(cli): fix issue with running individual sub-tests of Test_Tasks (#20646)
Closes https://github.com/coder/internal/issues/1112

Turns out sub-tests aren't ideal when you're running things that depend
on each other and need to be run in a certain order.
2025-11-03 10:13:19 +00:00
Atif Ali 3d411ddf4c chore: correct tooltip for JetBrains module in templates (#20638) 2025-11-03 14:02:19 +05:00
dependabot[bot] 26d029022d chore(examples/templates/tasks-docker): bump coder/claude-code to 3.4.4 (#20644)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-03 13:51:18 +05:00
david-fraley 2a5d86e2aa docs: add vacuum full on audit logs table recommendation (#20608) 2025-11-03 01:12:37 +00:00
dependabot[bot] eef18424e3 chore: bump coder/claude-code/coder from 3.3.2 to 3.4.4 in /dogfood/coder (#20642)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/claude-code/coder&package-manager=terraform&previous-version=3.3.2&new-version=3.4.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-03 00:40:27 +00:00
dependabot[bot] 926369b9f2 chore: bump coder/jetbrains/coder from 1.1.0 to 1.1.1 in /dogfood/coder (#20643)
[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=coder/jetbrains/coder&package-manager=terraform&previous-version=1.1.0&new-version=1.1.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-11-03 00:40:12 +00:00
dependabot[bot] e17b445e55 chore: bump @fontsource-variable/inter from 5.1.1 to 5.2.8 in /site (#20634)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-01 19:29:50 +05:00
dependabot[bot] dc5b877f26 chore: bump the react group across 1 directory with 4 updates (#20615)
Bumps the react group with 4 updates in the /site directory:
[react](https://github.com/facebook/react/tree/HEAD/packages/react),
[@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react),
[react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom)
and
[@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom).

Updates `react` from 19.1.1 to 19.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/facebook/react/releases">react's
releases</a>.</em></p>
<blockquote>
<h2>19.2.0 (Oct 1, 2025)</h2>
<p>Below is a list of all new features, APIs, and bug fixes.</p>
<p>Read the <a href="https://react.dev/blog/2025/10/01/react-19-2">React
19.2 release post</a> for more information.</p>
<h2>New React Features</h2>
<ul>
<li><a
href="https://react.dev/reference/react/Activity"><code>&lt;Activity&gt;</code></a>:
A new API to hide and restore the UI and internal state of its
children.</li>
<li><a
href="https://react.dev/reference/react/useEffectEvent"><code>useEffectEvent</code></a>
is a React Hook that lets you extract non-reactive logic into an <a
href="https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event">Effect
Event</a>.</li>
<li><a
href="https://react.dev/reference/react/cacheSignal"><code>cacheSignal</code></a>
(for RSCs) lets your know when the <code>cache()</code> lifetime is
over.</li>
<li><a
href="https://react.dev/reference/developer-tooling/react-performance-tracks">React
Performance tracks</a> appear on the Performance panel’s timeline in
your browser developer tools</li>
</ul>
<h2>New React DOM Features</h2>
<ul>
<li>Added resume APIs for partial pre-rendering with Web Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resume"><code>resume</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerender"><code>resumeAndPrerender</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Added resume APIs for partial pre-rendering with Node Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resumeToPipeableStream"><code>resumeToPipeableStream</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream"><code>resumeAndPrerenderToNodeStream</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Updated <a
href="https://react.dev/reference/react-dom/static/prerender"><code>prerender</code></a>
APIs to return a <code>postponed</code> state that can be passed to the
<code>resume</code> APIs.</li>
</ul>
<h2>Notable changes</h2>
<ul>
<li>React DOM now batches suspense boundary reveals, matching the
behavior of client side rendering. This change is especially noticeable
when animating the reveal of Suspense boundaries e.g. with the upcoming
<code>&lt;ViewTransition&gt;</code> Component. React will batch as much
reveals as possible before the first paint while trying to hit popular
first-contentful paint metrics.</li>
<li>Add Node Web Streams (<code>prerender</code>,
<code>renderToReadableStream</code>) to server-side-rendering APIs for
Node.js</li>
<li>Use underscore instead of <code>:</code> IDs generated by useId</li>
</ul>
<h2>All Changes</h2>
<h3>React</h3>
<ul>
<li><code>&lt;Activity /&gt;</code> was developed over many years,
starting before <code>ClassComponent.setState</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> and
many others)</li>
<li>Stringify context as &quot;SomeContext&quot; instead of
&quot;SomeContext.Provider&quot; (<a
href="https://github.com/kassens"><code>@​kassens</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33507">#33507</a>)</li>
<li>Include stack of cause of React instrumentation errors with
<code>%o</code> placeholder (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34198">#34198</a>)</li>
<li>Fix infinite <code>useDeferredValue</code> loop in popstate event
(<a href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32821">#32821</a>)</li>
<li>Fix a bug when an initial value was passed to
<code>useDeferredValue</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34376">#34376</a>)</li>
<li>Fix a crash when submitting forms with Client Actions (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33055">#33055</a>)</li>
<li>Hide/unhide the content of dehydrated suspense boundaries if they
resuspend (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32900">#32900</a>)</li>
<li>Avoid stack overflow on wide trees during Hot Reload (<a
href="https://github.com/sophiebits"><code>@​sophiebits</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34145">#34145</a>)</li>
<li>Improve Owner and Component stacks in various places (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/33629">#33629</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33724">#33724</a>,
<a
href="https://redirect.github.com/facebook/react/pull/32735">#32735</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33723">#33723</a>)</li>
<li>Add <code>cacheSignal</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33557">#33557</a>)</li>
</ul>
<h3>React DOM</h3>
<ul>
<li>Block on Suspensey Fonts during reveal of server-side-rendered
content (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33342">#33342</a>)</li>
<li>Use underscore instead of <code>:</code> for IDs generated by
<code>useId</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/32001">#32001</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33342">facebook/react#33342</a><a
href="https://redirect.github.com/facebook/react/pull/33099">#33099</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33422">#33422</a>)</li>
<li>Stop warning when ARIA 1.3 attributes are used (<a
href="https://github.com/Abdul-Omira"><code>@​Abdul-Omira</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34264">#34264</a>)</li>
<li>Allow <code>nonce</code> to be used on hoistable styles (<a
href="https://github.com/Andarist"><code>@​Andarist</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32461">#32461</a>)</li>
<li>Warn for using a React owned node as a Container if it also has text
content (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32774">#32774</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/facebook/react/blob/main/CHANGELOG.md">react's
changelog</a>.</em></p>
<blockquote>
<h2>19.2.0 (October 1st, 2025)</h2>
<p>Below is a list of all new features, APIs, and bug fixes.</p>
<p>Read the <a href="https://react.dev/blog/2025/10/01/react-19-2">React
19.2 release post</a> for more information.</p>
<h3>New React Features</h3>
<ul>
<li><a
href="https://react.dev/reference/react/Activity"><code>&lt;Activity&gt;</code></a>:
A new API to hide and restore the UI and internal state of its
children.</li>
<li><a
href="https://react.dev/reference/react/useEffectEvent"><code>useEffectEvent</code></a>
is a React Hook that lets you extract non-reactive logic into an <a
href="https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event">Effect
Event</a>.</li>
<li><a
href="https://react.dev/reference/react/cacheSignal"><code>cacheSignal</code></a>
(for RSCs) lets your know when the <code>cache()</code> lifetime is
over.</li>
<li><a
href="https://react.dev/reference/dev-tools/react-performance-tracks">React
Performance tracks</a> appear on the Performance panel’s timeline in
your browser developer tools</li>
</ul>
<h3>New React DOM Features</h3>
<ul>
<li>Added resume APIs for partial pre-rendering with Web Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resume"><code>resume</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerender"><code>resumeAndPrerender</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Added resume APIs for partial pre-rendering with Node Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resumeToPipeableStream"><code>resumeToPipeableStream</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream"><code>resumeAndPrerenderToNodeStream</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Updated <a
href="https://react.dev/reference/react-dom/static/prerender"><code>prerender</code></a>
APIs to return a <code>postponed</code> state that can be passed to the
<code>resume</code> APIs.</li>
</ul>
<h3>Notable changes</h3>
<ul>
<li>React DOM now batches suspense boundary reveals, matching the
behavior of client side rendering. This change is especially noticeable
when animating the reveal of Suspense boundaries e.g. with the upcoming
<code>&lt;ViewTransition&gt;</code> Component. React will batch as much
reveals as possible before the first paint while trying to hit popular
first-contentful paint metrics.</li>
<li>Add Node Web Streams (<code>prerender</code>,
<code>renderToReadableStream</code>) to server-side-rendering APIs for
Node.js</li>
<li>Use underscore instead of <code>:</code> IDs generated by useId</li>
</ul>
<h3>All Changes</h3>
<h4>React</h4>
<ul>
<li><code>&lt;Activity /&gt;</code> was developed over many years,
starting before <code>ClassComponent.setState</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> and
many others)</li>
<li>Stringify context as &quot;SomeContext&quot; instead of
&quot;SomeContext.Provider&quot; (<a
href="https://github.com/kassens"><code>@​kassens</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33507">#33507</a>)</li>
<li>Include stack of cause of React instrumentation errors with
<code>%o</code> placeholder (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34198">#34198</a>)</li>
<li>Fix infinite <code>useDeferredValue</code> loop in popstate event
(<a href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32821">#32821</a>)</li>
<li>Fix a bug when an initial value was passed to
<code>useDeferredValue</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34376">#34376</a>)</li>
<li>Fix a crash when submitting forms with Client Actions (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33055">#33055</a>)</li>
<li>Hide/unhide the content of dehydrated suspense boundaries if they
resuspend (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32900">#32900</a>)</li>
<li>Avoid stack overflow on wide trees during Hot Reload (<a
href="https://github.com/sophiebits"><code>@​sophiebits</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34145">#34145</a>)</li>
<li>Improve Owner and Component stacks in various places (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/33629">#33629</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33724">#33724</a>,
<a
href="https://redirect.github.com/facebook/react/pull/32735">#32735</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33723">#33723</a>)</li>
<li>Add <code>cacheSignal</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33557">#33557</a>)</li>
</ul>
<h4>React DOM</h4>
<ul>
<li>Block on Suspensey Fonts during reveal of server-side-rendered
content (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33342">#33342</a>)</li>
<li>Use underscore instead of <code>:</code> for IDs generated by
<code>useId</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/32001">#32001</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33342">facebook/react#33342</a><a
href="https://redirect.github.com/facebook/react/pull/33099">#33099</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33422">#33422</a>)</li>
<li>Stop warning when ARIA 1.3 attributes are used (<a
href="https://github.com/Abdul-Omira"><code>@​Abdul-Omira</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34264">#34264</a>)</li>
<li>Allow <code>nonce</code> to be used on hoistable styles (<a
href="https://github.com/Andarist"><code>@​Andarist</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32461">#32461</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/facebook/react/commit/5667a41fe4d81aa806f6c1e8814b17975e33b317"><code>5667a41</code></a>
Bump next prerelease version numbers (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34639">#34639</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/8bb7241f4c773376893701bfe8b8ff03687342a0"><code>8bb7241</code></a>
Bump useEffectEvent to Canary (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34610">#34610</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/e3c9656d20618ed321aea85cb3d844cbd1dce078"><code>e3c9656</code></a>
Ensure Performance Track are Clamped and Don't overlap (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34509">#34509</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/68f00c901c05e3a91f6cc77b660bc2334700f163"><code>68f00c9</code></a>
Release Activity in Canary (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34374">#34374</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/0e10ee906e3ea55e4d717d4db498e1159235b06b"><code>0e10ee9</code></a>
[Reconciler] Set ProfileMode for Host Root Fiber by default in dev (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34432">#34432</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/3bf8ab430eb2182e787e0f1c74c0d9ccab89e4ac"><code>3bf8ab4</code></a>
Add missing Activity export to development mode (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34439">#34439</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/1549bda33f0df963ae27a590b7191f3de99dad31"><code>1549bda</code></a>
[Flight] Only assign <code>_store</code> in dev mode when creating lazy
types (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34354">#34354</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/bb6f0c8d2f29754347db0ff28186dc89c128b6ca"><code>bb6f0c8</code></a>
[Flight] Fix wrong missing key warning when static child is blocked (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34350">#34350</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/05addfc6631ca72099631476b0a1592753858d30"><code>05addfc</code></a>
Update Flow to 0.266 (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34271">#34271</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/ec5dd0ab3acb206dd4aa46c6d5573c235c8eae98"><code>ec5dd0a</code></a>
Update Flow to 0.257 (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react/issues/34253">#34253</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/facebook/react/commits/v19.2.0/packages/react">compare
view</a></li>
</ul>
</details>
<br />

Updates `@types/react` from 19.1.17 to 19.2.2
<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 `react-dom` from 19.1.1 to 19.2.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/facebook/react/releases">react-dom's
releases</a>.</em></p>
<blockquote>
<h2>19.2.0 (Oct 1, 2025)</h2>
<p>Below is a list of all new features, APIs, and bug fixes.</p>
<p>Read the <a href="https://react.dev/blog/2025/10/01/react-19-2">React
19.2 release post</a> for more information.</p>
<h2>New React Features</h2>
<ul>
<li><a
href="https://react.dev/reference/react/Activity"><code>&lt;Activity&gt;</code></a>:
A new API to hide and restore the UI and internal state of its
children.</li>
<li><a
href="https://react.dev/reference/react/useEffectEvent"><code>useEffectEvent</code></a>
is a React Hook that lets you extract non-reactive logic into an <a
href="https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event">Effect
Event</a>.</li>
<li><a
href="https://react.dev/reference/react/cacheSignal"><code>cacheSignal</code></a>
(for RSCs) lets your know when the <code>cache()</code> lifetime is
over.</li>
<li><a
href="https://react.dev/reference/developer-tooling/react-performance-tracks">React
Performance tracks</a> appear on the Performance panel’s timeline in
your browser developer tools</li>
</ul>
<h2>New React DOM Features</h2>
<ul>
<li>Added resume APIs for partial pre-rendering with Web Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resume"><code>resume</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerender"><code>resumeAndPrerender</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Added resume APIs for partial pre-rendering with Node Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resumeToPipeableStream"><code>resumeToPipeableStream</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream"><code>resumeAndPrerenderToNodeStream</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Updated <a
href="https://react.dev/reference/react-dom/static/prerender"><code>prerender</code></a>
APIs to return a <code>postponed</code> state that can be passed to the
<code>resume</code> APIs.</li>
</ul>
<h2>Notable changes</h2>
<ul>
<li>React DOM now batches suspense boundary reveals, matching the
behavior of client side rendering. This change is especially noticeable
when animating the reveal of Suspense boundaries e.g. with the upcoming
<code>&lt;ViewTransition&gt;</code> Component. React will batch as much
reveals as possible before the first paint while trying to hit popular
first-contentful paint metrics.</li>
<li>Add Node Web Streams (<code>prerender</code>,
<code>renderToReadableStream</code>) to server-side-rendering APIs for
Node.js</li>
<li>Use underscore instead of <code>:</code> IDs generated by useId</li>
</ul>
<h2>All Changes</h2>
<h3>React</h3>
<ul>
<li><code>&lt;Activity /&gt;</code> was developed over many years,
starting before <code>ClassComponent.setState</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> and
many others)</li>
<li>Stringify context as &quot;SomeContext&quot; instead of
&quot;SomeContext.Provider&quot; (<a
href="https://github.com/kassens"><code>@​kassens</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33507">#33507</a>)</li>
<li>Include stack of cause of React instrumentation errors with
<code>%o</code> placeholder (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34198">#34198</a>)</li>
<li>Fix infinite <code>useDeferredValue</code> loop in popstate event
(<a href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32821">#32821</a>)</li>
<li>Fix a bug when an initial value was passed to
<code>useDeferredValue</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34376">#34376</a>)</li>
<li>Fix a crash when submitting forms with Client Actions (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33055">#33055</a>)</li>
<li>Hide/unhide the content of dehydrated suspense boundaries if they
resuspend (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32900">#32900</a>)</li>
<li>Avoid stack overflow on wide trees during Hot Reload (<a
href="https://github.com/sophiebits"><code>@​sophiebits</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34145">#34145</a>)</li>
<li>Improve Owner and Component stacks in various places (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/33629">#33629</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33724">#33724</a>,
<a
href="https://redirect.github.com/facebook/react/pull/32735">#32735</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33723">#33723</a>)</li>
<li>Add <code>cacheSignal</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33557">#33557</a>)</li>
</ul>
<h3>React DOM</h3>
<ul>
<li>Block on Suspensey Fonts during reveal of server-side-rendered
content (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33342">#33342</a>)</li>
<li>Use underscore instead of <code>:</code> for IDs generated by
<code>useId</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/32001">#32001</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33342">facebook/react#33342</a><a
href="https://redirect.github.com/facebook/react/pull/33099">#33099</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33422">#33422</a>)</li>
<li>Stop warning when ARIA 1.3 attributes are used (<a
href="https://github.com/Abdul-Omira"><code>@​Abdul-Omira</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34264">#34264</a>)</li>
<li>Allow <code>nonce</code> to be used on hoistable styles (<a
href="https://github.com/Andarist"><code>@​Andarist</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32461">#32461</a>)</li>
<li>Warn for using a React owned node as a Container if it also has text
content (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32774">#32774</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/facebook/react/blob/main/CHANGELOG.md">react-dom's
changelog</a>.</em></p>
<blockquote>
<h2>19.2.0 (October 1st, 2025)</h2>
<p>Below is a list of all new features, APIs, and bug fixes.</p>
<p>Read the <a href="https://react.dev/blog/2025/10/01/react-19-2">React
19.2 release post</a> for more information.</p>
<h3>New React Features</h3>
<ul>
<li><a
href="https://react.dev/reference/react/Activity"><code>&lt;Activity&gt;</code></a>:
A new API to hide and restore the UI and internal state of its
children.</li>
<li><a
href="https://react.dev/reference/react/useEffectEvent"><code>useEffectEvent</code></a>
is a React Hook that lets you extract non-reactive logic into an <a
href="https://react.dev/learn/separating-events-from-effects#declaring-an-effect-event">Effect
Event</a>.</li>
<li><a
href="https://react.dev/reference/react/cacheSignal"><code>cacheSignal</code></a>
(for RSCs) lets your know when the <code>cache()</code> lifetime is
over.</li>
<li><a
href="https://react.dev/reference/dev-tools/react-performance-tracks">React
Performance tracks</a> appear on the Performance panel’s timeline in
your browser developer tools</li>
</ul>
<h3>New React DOM Features</h3>
<ul>
<li>Added resume APIs for partial pre-rendering with Web Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resume"><code>resume</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerender"><code>resumeAndPrerender</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Added resume APIs for partial pre-rendering with Node Streams:
<ul>
<li><a
href="https://react.dev/reference/react-dom/server/resumeToPipeableStream"><code>resumeToPipeableStream</code></a>:
to resume a prerender to a stream.</li>
<li><a
href="https://react.dev/reference/react-dom/static/resumeAndPrerenderToNodeStream"><code>resumeAndPrerenderToNodeStream</code></a>:
to resume a prerender to HTML.</li>
</ul>
</li>
<li>Updated <a
href="https://react.dev/reference/react-dom/static/prerender"><code>prerender</code></a>
APIs to return a <code>postponed</code> state that can be passed to the
<code>resume</code> APIs.</li>
</ul>
<h3>Notable changes</h3>
<ul>
<li>React DOM now batches suspense boundary reveals, matching the
behavior of client side rendering. This change is especially noticeable
when animating the reveal of Suspense boundaries e.g. with the upcoming
<code>&lt;ViewTransition&gt;</code> Component. React will batch as much
reveals as possible before the first paint while trying to hit popular
first-contentful paint metrics.</li>
<li>Add Node Web Streams (<code>prerender</code>,
<code>renderToReadableStream</code>) to server-side-rendering APIs for
Node.js</li>
<li>Use underscore instead of <code>:</code> IDs generated by useId</li>
</ul>
<h3>All Changes</h3>
<h4>React</h4>
<ul>
<li><code>&lt;Activity /&gt;</code> was developed over many years,
starting before <code>ClassComponent.setState</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> and
many others)</li>
<li>Stringify context as &quot;SomeContext&quot; instead of
&quot;SomeContext.Provider&quot; (<a
href="https://github.com/kassens"><code>@​kassens</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33507">#33507</a>)</li>
<li>Include stack of cause of React instrumentation errors with
<code>%o</code> placeholder (<a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34198">#34198</a>)</li>
<li>Fix infinite <code>useDeferredValue</code> loop in popstate event
(<a href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32821">#32821</a>)</li>
<li>Fix a bug when an initial value was passed to
<code>useDeferredValue</code> (<a
href="https://github.com/acdlite"><code>@​acdlite</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34376">#34376</a>)</li>
<li>Fix a crash when submitting forms with Client Actions (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33055">#33055</a>)</li>
<li>Hide/unhide the content of dehydrated suspense boundaries if they
resuspend (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32900">#32900</a>)</li>
<li>Avoid stack overflow on wide trees during Hot Reload (<a
href="https://github.com/sophiebits"><code>@​sophiebits</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34145">#34145</a>)</li>
<li>Improve Owner and Component stacks in various places (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/33629">#33629</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33724">#33724</a>,
<a
href="https://redirect.github.com/facebook/react/pull/32735">#32735</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33723">#33723</a>)</li>
<li>Add <code>cacheSignal</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33557">#33557</a>)</li>
</ul>
<h4>React DOM</h4>
<ul>
<li>Block on Suspensey Fonts during reveal of server-side-rendered
content (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a> <a
href="https://redirect.github.com/facebook/react/pull/33342">#33342</a>)</li>
<li>Use underscore instead of <code>:</code> for IDs generated by
<code>useId</code> (<a
href="https://github.com/sebmarkbage"><code>@​sebmarkbage</code></a>, <a
href="https://github.com/eps1lon"><code>@​eps1lon</code></a>: <a
href="https://redirect.github.com/facebook/react/pull/32001">#32001</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33342">facebook/react#33342</a><a
href="https://redirect.github.com/facebook/react/pull/33099">#33099</a>,
<a
href="https://redirect.github.com/facebook/react/pull/33422">#33422</a>)</li>
<li>Stop warning when ARIA 1.3 attributes are used (<a
href="https://github.com/Abdul-Omira"><code>@​Abdul-Omira</code></a> <a
href="https://redirect.github.com/facebook/react/pull/34264">#34264</a>)</li>
<li>Allow <code>nonce</code> to be used on hoistable styles (<a
href="https://github.com/Andarist"><code>@​Andarist</code></a> <a
href="https://redirect.github.com/facebook/react/pull/32461">#32461</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/facebook/react/commit/861811347b8fa936b4a114fc022db9b8253b3d86"><code>8618113</code></a>
Bump scheduler version (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34671">#34671</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/1bd1f01f2a46fa453de5099280b54385ca7773b1"><code>1bd1f01</code></a>
Ship partial-prerendering APIs to Canary (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34633">#34633</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/2f0649a0b27516eaab549b18af15eed0420e3446"><code>2f0649a</code></a>
[Fizz] Remove <code>nonce</code> option from resume-and-prerender APIs
(<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34664">#34664</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/5667a41fe4d81aa806f6c1e8814b17975e33b317"><code>5667a41</code></a>
Bump next prerelease version numbers (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34639">#34639</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/e08f53b182fa63df6ec5938fec44d096343806d3"><code>e08f53b</code></a>
Match <code>react-dom/static</code> test entrypoints and published
entrypoints (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34599">#34599</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/8bb7241f4c773376893701bfe8b8ff03687342a0"><code>8bb7241</code></a>
Bump useEffectEvent to Canary (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34610">#34610</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/83c88ad470d680060f807ef81ed4c14b3b71fd3b"><code>83c88ad</code></a>
Handle fabric root level fragment with compareDocumentPosition (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34533">#34533</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/68f00c901c05e3a91f6cc77b660bc2334700f163"><code>68f00c9</code></a>
Release Activity in Canary (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34374">#34374</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/3168e08f8389d258de9eb7c8d19b9d44a0f250f2"><code>3168e08</code></a>
[flags] enable opt-in for enableDefaultTransitionIndicator (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/34373">#34373</a>)</li>
<li><a
href="https://github.com/facebook/react/commit/3434ff4f4b89ad9388c6109312ef95c14652ae21"><code>3434ff4</code></a>
Add scrollIntoView to fragment instances (<a
href="https://github.com/facebook/react/tree/HEAD/packages/react-dom/issues/32814">#32814</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/facebook/react/commits/v19.2.0/packages/react-dom">compare
view</a></li>
</ul>
</details>
<br />

Updates `@types/react-dom` from 19.1.11 to 19.2.2
<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 />

Updates `@types/react` from 19.1.17 to 19.2.2
<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.1.11 to 19.2.2
<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-11-01 11:56:11 +00:00
dependabot[bot] cb5ddec5c5 chore: bump monaco-editor from 0.53.0 to 0.54.0 in /site (#20626)
Bumps [monaco-editor](https://github.com/microsoft/monaco-editor) from
0.53.0 to 0.54.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/microsoft/monaco-editor/releases">monaco-editor's
releases</a>.</em></p>
<blockquote>
<h2>v0.54.0</h2>
<h2>Changes:</h2>
<ul>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5027">#5027</a>:
v0.54.0</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5019">#5019</a>:
updates monaco-editor-core</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5018">#5018</a>:
adds .js file extensions for esm build</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5012">#5012</a>:
Marks trusted-types as dev-dependency.</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4996">#4996</a>:
Fixes microsoft logo.</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4994">#4994</a>:
Fixes <a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4906">microsoft/monaco-editor#4906</a></li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4995">#4995</a>:
Removes unneeded mirror.</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4989">#4989</a>:
out/languages is no longer available</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4988">#4988</a>:
Fixes <a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4981">microsoft/monaco-editor#4981</a></li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4983">#4983</a>:
uses default mirror</li>
</ul>
<!-- raw HTML omitted -->
<ul>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4986">#4986</a>:
sets correct node version</li>
<li><a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4977">#4977</a>:
update samples</li>
</ul>
<p>This list of changes was <a
href="https://dev.azure.com/monacotools/Monaco/_build/results?buildId=362176&amp;view=logs">auto
generated</a>.<!-- raw HTML omitted --></p>
<h2>v0.54.0-dev-20251006</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20251005</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20251004</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20251003</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20251002</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20251001</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20250930</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20250929</h2>
<p>No release notes provided.</p>
<h2>v0.54.0-dev-20250928</h2>
<h2>Changes:</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md">monaco-editor's
changelog</a>.</em></p>
<blockquote>
<h2>[0.54.0]</h2>
<ul>
<li>Adds option <code>editor.mouseMiddleClickAction</code></li>
<li>Various bug fixes</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/7c2310116c57517348bbd868a21139f32454be22"><code>7c23101</code></a>
v0.54.0 (<a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5027">#5027</a>)</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/9242cdfd03eb811e8c480173cc80cceb513fc219"><code>9242cdf</code></a>
updates monaco-editor-core (<a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5019">#5019</a>)</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/05d44d842284c759f2fe5a9136508d97b23d085a"><code>05d44d8</code></a>
adds .js file extensions for esm build (<a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5018">#5018</a>)</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/2e93787361c915029103f9f351879cf1c168d61d"><code>2e93787</code></a>
Marks trusted-types as dev-dependency. (<a
href="https://redirect.github.com/microsoft/monaco-editor/issues/5012">#5012</a>)</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/1b33d5dced070e8e1b00f7b468693a5a780985bd"><code>1b33d5d</code></a>
Fixes microsoft logo. Closes <a
href="https://github.com/microsoft/monaco-editor/pull/">https://github.com/microsoft/monaco-editor/pull/</a>...</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/52d68ac7c4d071bb522d0bf81aaa180a2912de62"><code>52d68ac</code></a>
Fixes <a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4906">microsoft/monaco-editor#4906</a>
(<a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4994">#4994</a>)</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/52ad0e53206ae8d1c1917547cfd2d6863acc90d4"><code>52ad0e5</code></a>
Removes unneeded mirror. (<a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4995">#4995</a>)</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/2a3d33900cd48143ed21190be890c5496ecb6a85"><code>2a3d339</code></a>
Fixes <a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4992">microsoft/monaco-editor#4992</a></li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/7795b8c5c7cd3467aced8602d969a6341edfa28a"><code>7795b8c</code></a>
Fixes bug in min build by upgrading vite</li>
<li><a
href="https://github.com/microsoft/monaco-editor/commit/c5e6b5203456aa19d8a48533adcb01bf24c6ee85"><code>c5e6b52</code></a>
out/languages is no longer available (<a
href="https://redirect.github.com/microsoft/monaco-editor/issues/4989">#4989</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/microsoft/monaco-editor/compare/v0.53.0...v0.54.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=monaco-editor&package-manager=npm_and_yarn&previous-version=0.53.0&new-version=0.54.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-01 11:45:58 +00:00
dependabot[bot] eb020611a3 chore: bump storybook from 9.1.2 to 9.1.16 in /site (#20627)
Bumps
[storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/core)
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">storybook'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">storybook'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/ebd7ff59675c519bd50d81d005a69c921d943dbe"><code>ebd7ff5</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/32859">#32859</a>
from storybookjs/shilman/first-load-new-user</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/da2da6e60cc28e89189268be88d3d39bc763050b"><code>da2da6e</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/32862">#32862</a>
from storybookjs/yann/patch-dev-server-preset</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/b3129cd29460075e18507e84af8881725984aa21"><code>b3129cd</code></a>
fix exports</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/a78540afffbe1f69e21d7bf34e1c3b19c0ee1f04"><code>a78540a</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/32770">#32770</a>
from storybookjs/shilman/preview-first-load</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/0617aaa78035c9e032e986a1bd0a2e4affe51df5"><code>0617aaa</code></a>
improve typings of <code>storybook/internal/babel</code></li>
<li><a
href="https://github.com/storybookjs/storybook/commit/5a70f04b2993a822a43e67b449e8724a91502707"><code>5a70f04</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/32819">#32819</a>
from storybookjs/valentin/vitest-v4-support-2</li>
<li><a
href="https://github.com/storybookjs/storybook/commit/cae38158b53afb76008820f7e4591b33f87342d3"><code>cae3815</code></a>
Merge pull request <a
href="https://github.com/storybookjs/storybook/tree/HEAD/code/core/issues/32695">#32695</a>
from storybookjs/shilman/32687-play-method</li>
<li>Additional commits viewable in <a
href="https://github.com/storybookjs/storybook/commits/v9.1.16/code/core">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 storybook since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=storybook&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-11-01 11:44:05 +00:00
dependabot[bot] 697b3a0a06 chore: bump cmdk from 1.0.4 to 1.1.1 in /site (#20630)
Bumps [cmdk](https://github.com/pacocoursey/cmdk/tree/HEAD/cmdk) from
1.0.4 to 1.1.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pacocoursey/cmdk/releases">cmdk's
releases</a>.</em></p>
<blockquote>
<h2>v1.1.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix unintended double triggering of key bindings during IME
composition by <a
href="https://github.com/JaeSeoKim"><code>@​JaeSeoKim</code></a> in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/339">pacocoursey/cmdk#339</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/JaeSeoKim"><code>@​JaeSeoKim</code></a>
made their first contribution in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/339">pacocoursey/cmdk#339</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pacocoursey/cmdk/compare/v1.1.0...v1.1.1">https://github.com/pacocoursey/cmdk/compare/v1.1.0...v1.1.1</a></p>
<h2>v1.1.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix useCmdk return type by <a
href="https://github.com/lsmurray"><code>@​lsmurray</code></a> in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/329">pacocoursey/cmdk#329</a></li>
<li>fix: update the type of the defaultFilter by <a
href="https://github.com/muZk"><code>@​muZk</code></a> in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/338">pacocoursey/cmdk#338</a></li>
<li>[Accessibility] Use id instead of children by <a
href="https://github.com/UltimateGG"><code>@​UltimateGG</code></a> in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/254">pacocoursey/cmdk#254</a></li>
<li>Use <code>@radix-ui/react-compose-refs</code> to merge refs, save on
bundle size</li>
<li>Use React built-in <code>useSyncExternalStore</code> and remove
shim. Note that React 18 has always been a required peerDependency of
<code>cmdk</code></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/lsmurray"><code>@​lsmurray</code></a>
made their first contribution in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/329">pacocoursey/cmdk#329</a></li>
<li><a href="https://github.com/muZk"><code>@​muZk</code></a> made their
first contribution in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/338">pacocoursey/cmdk#338</a></li>
<li><a
href="https://github.com/UltimateGG"><code>@​UltimateGG</code></a> made
their first contribution in <a
href="https://redirect.github.com/pacocoursey/cmdk/pull/254">pacocoursey/cmdk#254</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/pacocoursey/cmdk/compare/v1.0.4...v1.1.0">https://github.com/pacocoursey/cmdk/compare/v1.0.4...v1.1.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/dip/cmdk/commit/fb4ea04e9ec211777fbb39c6104e3c5f2ee107d2"><code>fb4ea04</code></a>
v1.1.1</li>
<li><a
href="https://github.com/dip/cmdk/commit/f34d463c4aa2ae05aa934c458e69eebdcba997aa"><code>f34d463</code></a>
Fix unintended double triggering of key bindings during IME composition
(<a
href="https://github.com/pacocoursey/cmdk/tree/HEAD/cmdk/issues/339">#339</a>)</li>
<li><a
href="https://github.com/dip/cmdk/commit/2814a0083185132b2c023576e356d6c7a79e5aa8"><code>2814a00</code></a>
v1.1.0</li>
<li><a
href="https://github.com/dip/cmdk/commit/d46ed212bcabf143fb28ab2e85ec624525278b84"><code>d46ed21</code></a>
use built-in React uSES</li>
<li><a
href="https://github.com/dip/cmdk/commit/ec02b5e35df46e0f33e49e0c267fd07c7e3c727a"><code>ec02b5e</code></a>
use composeRefs from radix</li>
<li><a
href="https://github.com/dip/cmdk/commit/e5444d2341b6d07cc25861fb0c5c23d760803ce0"><code>e5444d2</code></a>
remove unused code</li>
<li><a
href="https://github.com/dip/cmdk/commit/34f3074c1f63878ca12a0f1cdb41e42c283847ec"><code>34f3074</code></a>
[Accessibility] Use id instead of children (<a
href="https://github.com/pacocoursey/cmdk/tree/HEAD/cmdk/issues/254">#254</a>)</li>
<li><a
href="https://github.com/dip/cmdk/commit/b2d94bdcc2a410c96e7b964c7aeb05b10c606a85"><code>b2d94bd</code></a>
fix: update the type of the defaultFilter (<a
href="https://github.com/pacocoursey/cmdk/tree/HEAD/cmdk/issues/338">#338</a>)</li>
<li><a
href="https://github.com/dip/cmdk/commit/9827edf89fc663e24188f9d715a0dca01a736d6d"><code>9827edf</code></a>
fix useCmdk return type (<a
href="https://github.com/pacocoursey/cmdk/tree/HEAD/cmdk/issues/329">#329</a>)</li>
<li>See full diff in <a
href="https://github.com/pacocoursey/cmdk/commits/v1.1.1/cmdk">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cmdk&package-manager=npm_and_yarn&previous-version=1.0.4&new-version=1.1.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-11-01 11:36:37 +00:00
dependabot[bot] acd6fe7aeb chore: bump @fontsource/source-code-pro from 5.2.5 to 5.2.7 in /site (#20632)
Bumps
[@fontsource/source-code-pro](https://github.com/fontsource/font-files/tree/HEAD/fonts/google/source-code-pro)
from 5.2.5 to 5.2.7.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/fontsource/font-files/commits/HEAD/fonts/google/source-code-pro">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@fontsource/source-code-pro&package-manager=npm_and_yarn&previous-version=5.2.5&new-version=5.2.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)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-01 11:34:30 +00:00
dependabot[bot] 0b214ad7f6 chore: bump semver from 7.7.2 to 7.7.3 in /site (#20620)
[//]: # (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 [semver](https://github.com/npm/node-semver) from 7.7.2 to 7.7.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/npm/node-semver/releases">semver's
releases</a>.</em></p>
<blockquote>
<h2>v7.7.3</h2>
<h2><a
href="https://github.com/npm/node-semver/compare/v7.7.2...v7.7.3">7.7.3</a>
(2025-10-06)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://github.com/npm/node-semver/commit/e37e0ca0b5fc910d2b1948d25dbc83cc3a0921ea"><code>e37e0ca</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/813">#813</a>
faster paths for compare (<a
href="https://redirect.github.com/npm/node-semver/issues/813">#813</a>)
(<a href="https://github.com/H4ad"><code>@​H4ad</code></a>)</li>
<li><a
href="https://github.com/npm/node-semver/commit/2471d7543e2e63d9d95358e2405e7e1cde926c36"><code>2471d75</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/811">#811</a>
x-range build metadata support (i529015)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><a
href="https://github.com/npm/node-semver/commit/8f05c87f56a4123259b8c6d9324f53eadb02e48f"><code>8f05c87</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/807">#807</a>
bump <code>@​npmcli/template-oss</code> from 4.25.0 to 4.25.1 (<a
href="https://redirect.github.com/npm/node-semver/issues/807">#807</a>)
(<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot],
<a
href="https://github.com/owlstronaut"><code>@​owlstronaut</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/npm/node-semver/blob/main/CHANGELOG.md">semver's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/npm/node-semver/compare/v7.7.2...v7.7.3">7.7.3</a>
(2025-10-06)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><a
href="https://github.com/npm/node-semver/commit/e37e0ca0b5fc910d2b1948d25dbc83cc3a0921ea"><code>e37e0ca</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/813">#813</a>
faster paths for compare (<a
href="https://redirect.github.com/npm/node-semver/issues/813">#813</a>)
(<a href="https://github.com/H4ad"><code>@​H4ad</code></a>)</li>
<li><a
href="https://github.com/npm/node-semver/commit/2471d7543e2e63d9d95358e2405e7e1cde926c36"><code>2471d75</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/811">#811</a>
x-range build metadata support (i529015)</li>
</ul>
<h3>Chores</h3>
<ul>
<li><a
href="https://github.com/npm/node-semver/commit/8f05c87f56a4123259b8c6d9324f53eadb02e48f"><code>8f05c87</code></a>
<a href="https://redirect.github.com/npm/node-semver/pull/807">#807</a>
bump <code>@​npmcli/template-oss</code> from 4.25.0 to 4.25.1 (<a
href="https://redirect.github.com/npm/node-semver/issues/807">#807</a>)
(<a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot],
<a
href="https://github.com/owlstronaut"><code>@​owlstronaut</code></a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/npm/node-semver/commit/a25789b09b1192fa8414c35f2cd679ae2e1d5192"><code>a25789b</code></a>
chore: release 7.7.3 (<a
href="https://redirect.github.com/npm/node-semver/issues/812">#812</a>)</li>
<li><a
href="https://github.com/npm/node-semver/commit/e37e0ca0b5fc910d2b1948d25dbc83cc3a0921ea"><code>e37e0ca</code></a>
fix: faster paths for compare (<a
href="https://redirect.github.com/npm/node-semver/issues/813">#813</a>)</li>
<li><a
href="https://github.com/npm/node-semver/commit/2471d7543e2e63d9d95358e2405e7e1cde926c36"><code>2471d75</code></a>
fix: x-range build metadata support</li>
<li><a
href="https://github.com/npm/node-semver/commit/8f05c87f56a4123259b8c6d9324f53eadb02e48f"><code>8f05c87</code></a>
chore: bump <code>@​npmcli/template-oss</code> from 4.25.0 to 4.25.1 (<a
href="https://redirect.github.com/npm/node-semver/issues/807">#807</a>)</li>
<li><a
href="https://github.com/npm/node-semver/commit/d17aebf8485edfe9dda982dab578c603d031e4ab"><code>d17aebf</code></a>
chore: bump <code>@​npmcli/template-oss</code> from 4.24.4 to 4.25.0 (<a
href="https://redirect.github.com/npm/node-semver/issues/797">#797</a>)</li>
<li><a
href="https://github.com/npm/node-semver/commit/3b03e3b4ecb28d609cd42a91c10da75ec1254976"><code>3b03e3b</code></a>
chore: bump <code>@​npmcli/template-oss</code> from 4.24.3 to 4.24.4 (<a
href="https://redirect.github.com/npm/node-semver/issues/790">#790</a>)</li>
<li>See full diff in <a
href="https://github.com/npm/node-semver/compare/v7.7.2...v7.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 semver since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=semver&package-manager=npm_and_yarn&previous-version=7.7.2&new-version=7.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-11-01 11:33:04 +00:00
dependabot[bot] 17438d9730 chore: bump react-router from 7.8.0 to 7.9.5 in /site (#20624)
Bumps
[react-router](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router)
from 7.8.0 to 7.9.5.
<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.5</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v795">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v795</a></p>
<h2>v7.9.4</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v794">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v794</a></p>
<h2>v7.9.3</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v793">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v793</a></p>
<h2>v7.9.2</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v792">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v792</a></p>
<h2>v7.9.1</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v791">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v791</a></p>
<h2>v7.9.0</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v790">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v790</a></p>
<h2>v7.8.2</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v782">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v782</a></p>
<h2>v7.8.1</h2>
<p>See the changelog for release notes: <a
href="https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v781">https://github.com/remix-run/react-router/blob/main/CHANGELOG.md#v781</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.5</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>Move RSCHydratedRouter and utils to <code>/dom</code> export. (<a
href="https://redirect.github.com/remix-run/react-router/pull/14457">#14457</a>)</p>
</li>
<li>
<p>useRoute: return type-safe <code>handle</code> (<a
href="https://redirect.github.com/remix-run/react-router/pull/14462">#14462</a>)</p>
<p>For example:</p>
<pre lang="ts"><code>// app/routes/admin.tsx
const handle = { hello: &quot;world&quot; };
</code></pre>
<pre lang="ts"><code>// app/routes/some-other-route.tsx
export default function Component() {
  const admin = useRoute(&quot;routes/admin&quot;);
if (!admin) throw new Error(&quot;Not nested within
'routes/admin'&quot;);
  console.log(admin.handle);
  //                ^? { hello: string }
}
</code></pre>
</li>
<li>
<p>Ensure action handlers run for routes with middleware even if no
loader is present (<a
href="https://redirect.github.com/remix-run/react-router/pull/14443">#14443</a>)</p>
</li>
<li>
<p>Add <code>unstable_instrumentations</code> API to allow users to add
observablity to their apps by instrumenting route loaders, actions,
middlewares, lazy, as well as server-side request handlers and client
side navigations/fetches (<a
href="https://redirect.github.com/remix-run/react-router/pull/14412">#14412</a>)</p>
<ul>
<li>Framework Mode:
<ul>
<li><code>entry.server.tsx</code>: <code>export const
unstable_instrumentations = [...]</code></li>
<li><code>entry.client.tsx</code>: <code>&lt;HydratedRouter
unstable_instrumentations={[...]} /&gt;</code></li>
</ul>
</li>
<li>Data Mode
<ul>
<li><code>createBrowserRouter(routes, { unstable_instrumentations: [...]
})</code></li>
</ul>
</li>
</ul>
<p>This also adds a new <code>unstable_pattern</code> parameter to
loaders/actions/middleware which contains the un-interpolated route
pattern (i.e., <code>/blog/:slug</code>) which is useful for aggregating
performance metrics by route</p>
</li>
</ul>
<h2>7.9.4</h2>
<h3>Patch Changes</h3>
<ul>
<li>
<p>handle external redirects in from server actions (<a
href="https://redirect.github.com/remix-run/react-router/pull/14400">#14400</a>)</p>
</li>
<li>
<p>New (unstable) <code>useRoute</code> hook for accessing data from
specific routes (<a
href="https://redirect.github.com/remix-run/react-router/pull/14407">#14407</a>)</p>
<p>For example, let's say you have an <code>admin</code> route somewhere
in your app and you want any child routes of <code>admin</code> to all
have access to the <code>loaderData</code> and <code>actionData</code>
from <code>admin.</code></p>
<pre lang="tsx"><code>// app/routes/admin.tsx
import { Outlet } from &quot;react-router&quot;;
<p>export const loader = () =&gt; ({ message: &quot;Hello, loader!&quot;
});
</code></pre></p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/remix-run/react-router/commit/a1918125144aecd8ac5dd62ad3b682877f06106f"><code>a191812</code></a>
chore: Update version for release (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14485">#14485</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/74bef786708cf6fe626649adca60a39bce898f39"><code>74bef78</code></a>
chore: Update version for release (pre) (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14469">#14469</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/c0577e4ad2347a097c7249ea1e7935fef3b53b27"><code>c0577e4</code></a>
Merge branch 'main' into release-next</li>
<li><a
href="https://github.com/remix-run/react-router/commit/0163df4848a05fca60f0390b67e9615e9f4b40f9"><code>0163df4</code></a>
fix(react-router): run action handlers for routes with middleware even
if no ...</li>
<li><a
href="https://github.com/remix-run/react-router/commit/c84016b8847250f8cabab291adf44a12a46e3f2c"><code>c84016b</code></a>
Minor updates for instrumentations (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14467">#14467</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/adadca5534c3bfa43fcd61adbf00c78d56d43c77"><code>adadca5</code></a>
Add unstable_instrumentations API (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14412">#14412</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/dea842d8d938c4f39503a8f3a97e424d2b73b16a"><code>dea842d</code></a>
fix: move RSCHydratedRouter and utils to <code>/dom</code> export (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14457">#14457</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/1d1b18809eac4bd9e4fd0887dcfa1f225e10b0bc"><code>1d1b188</code></a>
useRoute: return type-safe <code>handle</code> (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14462">#14462</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/3e3a223ee90c1fee3da01daf6866ad2f5bdf62ba"><code>3e3a223</code></a>
docs: fix references (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14441">#14441</a>)</li>
<li><a
href="https://github.com/remix-run/react-router/commit/158847e11664bc47534bf8f334bc9d630ea79a70"><code>158847e</code></a>
fix: Fix invalid markdown link for createHashRouter (<a
href="https://github.com/remix-run/react-router/tree/HEAD/packages/react-router/issues/14434">#14434</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/remix-run/react-router/commits/react-router@7.9.5/packages/react-router">compare
view</a></li>
</ul>
</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.8.0&new-version=7.9.5)](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-01 11:32:40 +00:00
dependabot[bot] 279288affe chore: bump knip from 5.64.1 to 5.66.4 in /site (#20636)
[//]: # (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 [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip)
from 5.64.1 to 5.66.4.
<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.66.4</h2>
<ul>
<li>Add experimental nextjs conventions support (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1322">#1322</a>)
(b7acf1fc7038f31797f82ec55a007cb73e9af08c) - thanks <a
href="https://github.com/vinnymac"><code>@​vinnymac</code></a>!</li>
<li>Fix one character getting removed too much when fixing unused
exported type (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1324">#1324</a>)
(935cf5d21d75ab19fd4783efe536a14a27bd9d6b) - thanks <a
href="https://github.com/ulrichstark"><code>@​ulrichstark</code></a>!</li>
<li>Set --fix if --fix-types or --allow-remove-files is set (close <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1325">#1325</a>)
(d4b56e721c59f80c30ccd74c76f45cdeb9361dfa)</li>
<li>Update sponsors page (87c388047fde4e81ea39c3b8bbada61e51f8da7c)</li>
<li>Re-gen plugins list (a7d1ece38157ed7c1b177e0bf1ad3fed0fe63c37)</li>
<li>Update oxc-resolver (close <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1316">#1316</a>)
(3eaad532be46d12c46ea6b80352216e4e355ec4e)</li>
</ul>
<h2>Release 5.66.3</h2>
<ul>
<li>feat(next): add proxy to entry file pattern (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1318">#1318</a>)
(c730727babd1321c5c1037178651113360ed38bc) - thanks <a
href="https://github.com/filipweilid"><code>@​filipweilid</code></a>!</li>
<li>Add new vitest built-in reporters (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1320">#1320</a>)
(3bfdc80de8fe4e8a2d74ab99669c011e4cce2162) - thanks <a
href="https://github.com/ocavue"><code>@​ocavue</code></a>!</li>
<li>Fix unwanted duplicates reports if disabled
(8012b548fe344540d6db1b5a9e7bfe24b9f0e411)</li>
<li>Fix bug in import map updater
(90fc72e44d02c3b0919dd8ac60ec67fd8ab38fe0)</li>
<li>Increase precision for named import pos
(4eb6dd3636bd2fc2df473ae960c8c37f930099a1)</li>
<li>Turn off rule if that issue type is disabled
(4bc66d87396cea4dc079163b06bef9c4415cea21)</li>
<li>Move types (b7cf6aa0d2458e948b2066f726f49022d2683c50)</li>
<li>Get text of element.name (resolves <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1315">#1315</a>)
(c39e7757c0e87d98a0601a202fecff8bd0e0384f)</li>
</ul>
<h2>Release 5.66.2</h2>
<ul>
<li>Fix negated patterns from package.json#exports (related to <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1308">#1308</a>)
(2464f3704a11b0c6d1f71a1850f4fa928e6c623f)</li>
<li>Entries in rsbuild config are production entries (resolves <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1309">#1309</a>)
(9eebc5574aa964f12a91f9bc8bb415f79c35aeed)</li>
<li>Add label for entry paths from package.json
(42370b27eff932c25d2abfabb5313b20a65fbed5)</li>
</ul>
<h2>Release 5.66.1</h2>
<ul>
<li>Revive some tests in Node
(20690d196775e8391dd50ae23398e57e8bd74267)</li>
<li>Fix up <code>SymbolType</code> and reuse <code>SYMBOL_TYPE</code>
(resolves <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1306">#1306</a>)
(d7c1c8313c751419588c0bec3e5e3b1f7e636ba0)</li>
<li>Minor refactor (3143c4e40303f1a1001035a04c41da14ccdb42f6)</li>
<li>Make <code>defineNuxtConfig</code> writable and deletable (resolves
<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1307">#1307</a>)
(c31a77f923452b4df88fe9a2bb9914ee400afbfd)</li>
<li>Fix up progress flag (c761a9d3647be2f7910c6992377695582e6a2d1e)</li>
<li>Clear screen in watch mode
(fb3ff4e9d7e6a466312d290f01ff68adc70e4276)</li>
<li>Refactor watch mode (661440e8c822894e889524d5df5e0f9220c1c8be)</li>
<li>Re-play previously unretained issues in watch mode
(9b96730aaa35bcfa13c210c1fba6485595918d03)</li>
<li>Format &amp; lint (7776ae839f85c6d454894f019c79c3a0bfca2a3d)</li>
</ul>
<h2>Release 5.66.0</h2>
<ul>
<li>Add coverage for <code>ignoreFiles</code> feat
(87ca476cdc1ebcc7637e2ff17a88e4fd7dfe790d)</li>
<li>update eleventy API to add addBundle() fix (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1300">#1300</a>)
(ed2acecbdbcf3eece05c4e5777ac5bb4f3620e06) - thanks <a
href="https://github.com/hoardinghopes"><code>@​hoardinghopes</code></a>!</li>
<li>feat: add danger plugin (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1302">#1302</a>)
(d9e969da0eefce9c7e0060eb352aef8250f2004e) - thanks <a
href="https://github.com/what1s1ove"><code>@​what1s1ove</code></a>!</li>
<li>feat: add support for ignoring specific issue types per file pattern
(<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1303">#1303</a>)
(673893ac5cc1342ec85ca468ffeaff6ac239239c) - thanks <a
href="https://github.com/rfalke-rtl"><code>@​rfalke-rtl</code></a>!</li>
<li>Speed up JSON load (83ca88f4c007402d3a0b2b479b81a292ca76af5b)</li>
<li>Add JSON5 explainer to error (closes <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1297">#1297</a>)
(cb926ca9eaec6b03b218ed76f06b690a13db2485)</li>
<li>Add <code>ignoreIssues</code> to JSON Schema
(90056915e49be7b36a03cb35ec563876110d16c9)</li>
<li>Update docs (b4b89299399fa089ab85b8ea432b4cb753e11964)</li>
<li>Oh, CI (b153f93143b54288afaee09d626b43d9d6803c44)</li>
<li>Fix lint issues (0ccfda67af6190b8184ef6fe94036e79c9a06f1d)</li>
</ul>
<h2>Release 5.65.0</h2>
<ul>
<li>Release 5.64.3 (157ae943fa2a7b16321c1c6c5fff87ba9d6f3566)</li>
<li>Oops (f7ce7d7a0fed6acd4d22d8825dc3de08bff5df15)</li>
<li>Fix some typos in docs and code comments (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1299">#1299</a>)
(715d7cc75f4349547fba049839b4dca253acf57f) - thanks <a
href="https://github.com/jdufresne"><code>@​jdufresne</code></a>!</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/2d44390aeb82cf5a88df1ee52b45c6044ab87069"><code>2d44390</code></a>
Release 5.66.4</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/3eaad532be46d12c46ea6b80352216e4e355ec4e"><code>3eaad53</code></a>
Update oxc-resolver (close <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1316">#1316</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/d4b56e721c59f80c30ccd74c76f45cdeb9361dfa"><code>d4b56e7</code></a>
Set --fix if --fix-types or --allow-remove-files is set (close <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1325">#1325</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/935cf5d21d75ab19fd4783efe536a14a27bd9d6b"><code>935cf5d</code></a>
Fix one character getting removed too much when fixing unused exported
type (...</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/b7acf1fc7038f31797f82ec55a007cb73e9af08c"><code>b7acf1f</code></a>
Add experimental nextjs conventions support (<a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1322">#1322</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/9b1a40f2e3ae61965c87840692ab5790518e0b12"><code>9b1a40f</code></a>
Release 5.66.3</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/c39e7757c0e87d98a0601a202fecff8bd0e0384f"><code>c39e775</code></a>
Get text of element.name (resolves <a
href="https://github.com/webpro-nl/knip/tree/HEAD/packages/knip/issues/1315">#1315</a>)</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/b7cf6aa0d2458e948b2066f726f49022d2683c50"><code>b7cf6aa</code></a>
Move types</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/4bc66d87396cea4dc079163b06bef9c4415cea21"><code>4bc66d8</code></a>
Turn off rule if that issue type is disabled</li>
<li><a
href="https://github.com/webpro-nl/knip/commit/4eb6dd3636bd2fc2df473ae960c8c37f930099a1"><code>4eb6dd3</code></a>
Increase precision for named import pos</li>
<li>Additional commits viewable in <a
href="https://github.com/webpro-nl/knip/commits/5.66.4/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.64.1&new-version=5.66.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-01 11:32:10 +00:00
dependabot[bot] c571995a42 chore: bump protobufjs from 7.4.0 to 7.5.4 in /site (#20635)
Bumps [protobufjs](https://github.com/protobufjs/protobuf.js) from 7.4.0
to 7.5.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/protobufjs/protobuf.js/releases">protobufjs's
releases</a>.</em></p>
<blockquote>
<h2>protobufjs: v7.5.4</h2>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.3...protobufjs-v7.5.4">7.5.4</a>
(2025-08-15)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>invalid syntax in descriptor.proto (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2092">#2092</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/5a3769a465fead089a533ad55c21d069299df760">5a3769a</a>)</li>
</ul>
<h2>protobufjs: v7.5.3</h2>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.2...protobufjs-v7.5.3">7.5.3</a>
(2025-05-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>descriptor extensions handling post-editions (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2075">#2075</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/6e255d4ad6982cc857f26e1731c2cedcf5796f68">6e255d4</a>)</li>
</ul>
<h2>protobufjs: v7.5.2</h2>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.1...protobufjs-v7.5.2">7.5.2</a>
(2025-05-14)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>ensure that types are always resolved (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2068">#2068</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/4b51cb2b8450b77f9f5de1c562e7fae93b19d040">4b51cb2</a>)</li>
</ul>
<h2>protobufjs: v7.5.1</h2>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.0...protobufjs-v7.5.1">7.5.1</a>
(2025-05-08)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>optimize regressions from editions implementations (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2066">#2066</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/6406d4c18afae309fc7b5f4a24d9674d85da180b">6406d4c</a>)</li>
<li>reserved field inside group blocks fail parsing (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2058">#2058</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/56782bff0c4b5132806eb1a6bc4d08f930c4aaad">56782bf</a>)</li>
</ul>
<h2>protobufjs: v7.5.0</h2>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.0">7.5.0</a>
(2025-04-15)</h2>
<h3>Features</h3>
<ul>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/f04ded3a03a3ddd383f0228e2fe2627a51f31aa3">f04ded3</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/ac9a3b9fe3134d48187e41b08d54ffaceddc6c1b">ac9a3b9</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/e5ca5c84e326699e10258367883a54934e0bfe14">e5ca5c8</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a84409b47f9ba0dba56da1af8054fb54f85d85a1">a84409b</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/9c5a178c4b59e0aa65ecac0bd7420171213b2ff9">9c5a178</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/b2c686721e3b63d092419fa1cbe58e1deb89534e">b2c6867</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/60f3e51087ca2c247473410f39331e1c766aefef">60f3e51</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a6563617de04d510d6e8865eb6c5067f10247f64">a656361</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/869a95b1e5f553c76243aac45619061407a41084">869a95b</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/b936af4219181811e98f72d4902a40e1c3f1f3be">b936af4</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a938467e476b3e168b8df1b89452864731e6a373">a938467</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/protobufjs/protobuf.js/blob/master/CHANGELOG.md">protobufjs's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.3...protobufjs-v7.5.4">7.5.4</a>
(2025-08-15)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>invalid syntax in descriptor.proto (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2092">#2092</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/5a3769a465fead089a533ad55c21d069299df760">5a3769a</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.2...protobufjs-v7.5.3">7.5.3</a>
(2025-05-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>descriptor extensions handling post-editions (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2075">#2075</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/6e255d4ad6982cc857f26e1731c2cedcf5796f68">6e255d4</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.1...protobufjs-v7.5.2">7.5.2</a>
(2025-05-14)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>ensure that types are always resolved (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2068">#2068</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/4b51cb2b8450b77f9f5de1c562e7fae93b19d040">4b51cb2</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.5.0...protobufjs-v7.5.1">7.5.1</a>
(2025-05-08)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>optimize regressions from editions implementations (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2066">#2066</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/6406d4c18afae309fc7b5f4a24d9674d85da180b">6406d4c</a>)</li>
<li>reserved field inside group blocks fail parsing (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2058">#2058</a>)
(<a
href="https://github.com/protobufjs/protobuf.js/commit/56782bff0c4b5132806eb1a6bc4d08f930c4aaad">56782bf</a>)</li>
</ul>
<h2><a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.0">7.5.0</a>
(2025-04-15)</h2>
<h3>Features</h3>
<ul>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/f04ded3a03a3ddd383f0228e2fe2627a51f31aa3">f04ded3</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/ac9a3b9fe3134d48187e41b08d54ffaceddc6c1b">ac9a3b9</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/e5ca5c84e326699e10258367883a54934e0bfe14">e5ca5c8</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a84409b47f9ba0dba56da1af8054fb54f85d85a1">a84409b</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/9c5a178c4b59e0aa65ecac0bd7420171213b2ff9">9c5a178</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/b2c686721e3b63d092419fa1cbe58e1deb89534e">b2c6867</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/60f3e51087ca2c247473410f39331e1c766aefef">60f3e51</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a6563617de04d510d6e8865eb6c5067f10247f64">a656361</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/869a95b1e5f553c76243aac45619061407a41084">869a95b</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/b936af4219181811e98f72d4902a40e1c3f1f3be">b936af4</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/a938467e476b3e168b8df1b89452864731e6a373">a938467</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/1af8454538b63d58b822ea9d20b935f2ac9f158c">1af8454</a>)</li>
<li>add Edition 2023 Support (<a
href="https://github.com/protobufjs/protobuf.js/commit/785416fd2b9827e4cb9bfccd823c3b6836baffb0">785416f</a>)</li>
<li>add feature resolution (<a
href="https://github.com/protobufjs/protobuf.js/commit/a9ffc8a7b593209642fc9d89e884ac6c4e746494">a9ffc8a</a>)</li>
<li>add feature resolution and tests (<a
href="https://github.com/protobufjs/protobuf.js/commit/68b5339ea1936c90f526983da29b4267d20f9a51">68b5339</a>)</li>
<li>add feature resolution for protobuf editions (<a
href="https://github.com/protobufjs/protobuf.js/commit/547afa26f76e22e5463a17aec082b0b60cd951d8">547afa2</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/827ff8e48253e9041f19ac81168aa046dbdfb041"><code>827ff8e</code></a>
chore: release master (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2093">#2093</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/5a3769a465fead089a533ad55c21d069299df760"><code>5a3769a</code></a>
fix: invalid syntax in descriptor.proto (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2092">#2092</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/f42297b29d15c8e0382744a83f5147a1aa978f42"><code>f42297b</code></a>
chore: release master (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2076">#2076</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/6e255d4ad6982cc857f26e1731c2cedcf5796f68"><code>6e255d4</code></a>
fix: descriptor extensions handling post-editions (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2075">#2075</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/9467abe5af0aa5de3e4cf26b9e1a85c97f5eebd0"><code>9467abe</code></a>
chore: release master (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2070">#2070</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/4b51cb2b8450b77f9f5de1c562e7fae93b19d040"><code>4b51cb2</code></a>
fix: ensure that types are always resolved (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2068">#2068</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/69cced8e00216f1aed69593187ac0c2e34807208"><code>69cced8</code></a>
chore: release master (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2067">#2067</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/6406d4c18afae309fc7b5f4a24d9674d85da180b"><code>6406d4c</code></a>
fix: optimize regressions from editions implementations (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2066">#2066</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/56782bff0c4b5132806eb1a6bc4d08f930c4aaad"><code>56782bf</code></a>
fix: reserved field inside group blocks fail parsing (<a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2058">#2058</a>)</li>
<li><a
href="https://github.com/protobufjs/protobuf.js/commit/1dbcfe322899aca50fb82916db7802f647f23f0e"><code>1dbcfe3</code></a>
Merge pull request <a
href="https://redirect.github.com/protobufjs/protobuf.js/issues/2035">#2035</a>
from protobufjs/release-please--branches--master</li>
<li>Additional commits viewable in <a
href="https://github.com/protobufjs/protobuf.js/compare/protobufjs-v7.4.0...protobufjs-v7.5.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=protobufjs&package-manager=npm_and_yarn&previous-version=7.4.0&new-version=7.5.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-01 11:31:35 +00:00
dependabot[bot] bea2f8633a chore: bump undici from 6.21.3 to 6.22.0 in /site (#20631)
Bumps [undici](https://github.com/nodejs/undici) from 6.21.3 to 6.22.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/nodejs/undici/releases">undici's
releases</a>.</em></p>
<blockquote>
<h2>v6.22.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: fix wrong stream canceled up after cloning (v6) by <a
href="https://github.com/snyamathi"><code>@​snyamathi</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4414">nodejs/undici#4414</a></li>
<li>[Backport v6.x] fix: fix EnvHttpProxyAgent for the Node.js bundle by
<a
href="https://github.com/github-actions"><code>@​github-actions</code></a>[bot]
in <a
href="https://redirect.github.com/nodejs/undici/pull/4432">nodejs/undici#4432</a></li>
<li>feat(ProxyAgent): match Curl behavior in HTTP-&gt;HTTP Proxy
connections (<a
href="https://redirect.github.com/nodejs/undici/issues/4180">#4180</a>)
by <a href="https://github.com/metcoder95"><code>@​metcoder95</code></a>
in <a
href="https://redirect.github.com/nodejs/undici/pull/4433">nodejs/undici#4433</a></li>
<li>feat(ProxyAgent) improve Curl-y behavior in HTTP-&gt;HTTP Proxy
connections (<a
href="https://redirect.github.com/nodejs/undici/issues/4180">#4180</a>)
(<a
href="https://redirect.github.com/nodejs/undici/issues/4340">#4340</a>)
by <a href="https://github.com/metcoder95"><code>@​metcoder95</code></a>
in <a
href="https://redirect.github.com/nodejs/undici/pull/4445">nodejs/undici#4445</a></li>
<li>Backport 4472 to v6.x by <a
href="https://github.com/Uzlopak"><code>@​Uzlopak</code></a> in <a
href="https://redirect.github.com/nodejs/undici/pull/4480">nodejs/undici#4480</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/nodejs/undici/compare/v6.21.3...v6.22.0">https://github.com/nodejs/undici/compare/v6.21.3...v6.22.0</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/nodejs/undici/commit/f9c91853e7a73d8148e3d2914f8200dd160dd050"><code>f9c9185</code></a>
Bumped v6.22.0</li>
<li><a
href="https://github.com/nodejs/undici/commit/f670f2a27970abfd6c5b56e692f025067824726f"><code>f670f2a</code></a>
feat: make UndiciErrors reliable to instanceof (<a
href="https://redirect.github.com/nodejs/undici/issues/4472">#4472</a>)
(<a
href="https://redirect.github.com/nodejs/undici/issues/4480">#4480</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/422e39771877f62737f9e5fbdd336aaa22610a5d"><code>422e397</code></a>
feat(ProxyAgent) improve Curl-y behavior in HTTP-&gt;HTTP Proxy
connections (<a
href="https://redirect.github.com/nodejs/undici/issues/41">#41</a>...</li>
<li><a
href="https://github.com/nodejs/undici/commit/4a06ffe61fa11028a4443974ec0b0a793ee6c836"><code>4a06ffe</code></a>
feat(ProxyAgent): match Curl behavior in HTTP-&gt;HTTP Proxy connections
(<a
href="https://redirect.github.com/nodejs/undici/issues/4180">#4180</a>)...</li>
<li><a
href="https://github.com/nodejs/undici/commit/4cb397400e319505647e1705f535848db5949c18"><code>4cb3974</code></a>
fix: fix EnvHttpProxyAgent for the Node.js bundle (<a
href="https://redirect.github.com/nodejs/undici/issues/4064">#4064</a>)
(<a
href="https://redirect.github.com/nodejs/undici/issues/4432">#4432</a>)</li>
<li><a
href="https://github.com/nodejs/undici/commit/44c23e5e166a30dd57eed47f1d4911b8ba77ce89"><code>44c23e5</code></a>
fix: fix wrong stream canceled up after cloning (v6) (<a
href="https://redirect.github.com/nodejs/undici/issues/4414">#4414</a>)</li>
<li>See full diff in <a
href="https://github.com/nodejs/undici/compare/v6.21.3...v6.22.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=undici&package-manager=npm_and_yarn&previous-version=6.21.3&new-version=6.22.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-01 11:27:04 +00:00
dependabot[bot] dc9166b4cd chore: bump recharts from 2.15.0 to 2.15.4 in /site (#20629)
Bumps [recharts](https://github.com/recharts/recharts) from 2.15.0 to
2.15.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/recharts/recharts/releases">recharts's
releases</a>.</em></p>
<blockquote>
<h2>v2.15.4</h2>
<h2>What's Changed</h2>
<p>Last 2.x patch - releasing since the <code>@babel/runtime</code>
vulnerability is showing up in some security scans. Hoping to release
3.0 on 6/22 🚀</p>
<h3>Fix</h3>
<ul>
<li><code>X/YAxis</code>: fix issue where recharts class names did not
get passed to custom tick components by <a
href="https://github.com/MyungAe"><code>@​MyungAe</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5840">recharts/recharts#5840</a></li>
<li><code>Bar</code>: allow <code>minPointSize</code> function to
receive null and undefined values by <a
href="https://github.com/eino"><code>@​eino</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5947">recharts/recharts#5947</a></li>
<li><code>TypeScript</code>: fix issue which caused build errors when
<code>allowSyntheticDefaultImports: false</code> by <a
href="https://github.com/tfaller"><code>@​tfaller</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5810">recharts/recharts#5810</a></li>
</ul>
<h3>Security</h3>
<ul>
<li>resolve <code>@​babel/runtime</code> ReDoS vulnerability
(SNYK-JS-BABELRUNTIME-10044504) by <a
href="https://github.com/moehaje"><code>@​moehaje</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5969">recharts/recharts#5969</a>
<ul>
<li>recharts isn't vulnerable to this per-se, but it does show up in
security tooling like snyk</li>
</ul>
</li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/moehaje"><code>@​moehaje</code></a> made
their first contribution in <a
href="https://redirect.github.com/recharts/recharts/pull/5969">recharts/recharts#5969</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/recharts/recharts/compare/v2.15.3...v2.15.4">https://github.com/recharts/recharts/compare/v2.15.3...v2.15.4</a></p>
<h2>v2.15.3</h2>
<p>Last patch release before 3.0 🚀</p>
<h2>What's Changed</h2>
<h3>Fix</h3>
<ul>
<li><code>XAxis</code>: fix padding calculation for
<code>padding=&quot;gap&quot;</code> and
<code>padding=&quot;no-gap&quot;</code> when XAxis is type number by <a
href="https://github.com/jackfletch"><code>@​jackfletch</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5759">recharts/recharts#5759</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/recharts/recharts/compare/v2.15.2...v2.15.3">https://github.com/recharts/recharts/compare/v2.15.2...v2.15.3</a></p>
<h2>v2.15.2</h2>
<h2>What's Changed</h2>
<p>Few bugfixes and bug fix backports for 2.x</p>
<h4>Fix</h4>
<ul>
<li><code>Bar/Rectangle</code>: add index back to Bar Rectangle key to
prevent duplicate key issues by <a
href="https://github.com/ckifer"><code>@​ckifer</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5561">recharts/recharts#5561</a></li>
<li><code>Dot</code>: re-include <code>points</code> object in dotProps
by <a
href="https://github.com/brodriguezmilla"><code>@​brodriguezmilla</code></a>
in <a
href="https://redirect.github.com/recharts/recharts/pull/5657">recharts/recharts#5657</a></li>
<li><code>Tooltip</code>: add <code>SVGProps</code> to Tooltip payload
type to account for svg properties such as opacity passed by the user by
<a href="https://github.com/ally1002"><code>@​ally1002</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5712">recharts/recharts#5712</a></li>
<li><code>Tooltip/Bar</code>: fix <code>activeBar</code> prop not
working when tooltip <code>shared={false}</code> by <a
href="https://github.com/nizans"><code>@​nizans</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5718">recharts/recharts#5718</a></li>
<li><code>General</code>: allow <code>data-*</code> props to be spread
on svg elements and not be filtered out by <a
href="https://github.com/prtmwrkr"><code>@​prtmwrkr</code></a> in <a
href="https://redirect.github.com/recharts/recharts/pull/5666">recharts/recharts#5666</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/brodriguezmilla"><code>@​brodriguezmilla</code></a>
made their first contribution in <a
href="https://redirect.github.com/recharts/recharts/pull/5657">recharts/recharts#5657</a></li>
<li><a href="https://github.com/nizans"><code>@​nizans</code></a> made
their first contribution in <a
href="https://redirect.github.com/recharts/recharts/pull/5718">recharts/recharts#5718</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/recharts/recharts/commit/7baebfe02c196b52d725b82cbbbdc7cb3a235caa"><code>7baebfe</code></a>
2.15.4</li>
<li><a
href="https://github.com/recharts/recharts/commit/a059da31f3ff8f0f451f541f1be48b93cedf6f6a"><code>a059da3</code></a>
fix: resolve <code>@​babel/runtime</code> ReDoS vulnerability
(SNYK-JS-BABELRUNTIME-1004450...</li>
<li><a
href="https://github.com/recharts/recharts/commit/b835f0e97732e049fa8a8a4ba7ec983d2134d8b7"><code>b835f0e</code></a>
feat: allow minPointSize function to receive null and undefined values
(2.x) ...</li>
<li><a
href="https://github.com/recharts/recharts/commit/7921cda6f584a7e31112c89d073c6097326da4a4"><code>7921cda</code></a>
fix: combine custom-tick-className and cartesian-axis-tick-value (<a
href="https://redirect.github.com/recharts/recharts/issues/5840">#5840</a>)</li>
<li><a
href="https://github.com/recharts/recharts/commit/5a3057ab9e46911082c5b1403358f4233b32defe"><code>5a3057a</code></a>
Import react with namespace import (<a
href="https://redirect.github.com/recharts/recharts/issues/5810">#5810</a>)</li>
<li><a
href="https://github.com/recharts/recharts/commit/bfd18c27d965c32529afffd851f3bb79920513c1"><code>bfd18c2</code></a>
2.15.3</li>
<li><a
href="https://github.com/recharts/recharts/commit/6d655429a78b7f83d9ec079adaa59558dd337dfe"><code>6d65542</code></a>
Fix XAxis padding calculation (<a
href="https://redirect.github.com/recharts/recharts/issues/5759">#5759</a>)</li>
<li><a
href="https://github.com/recharts/recharts/commit/2ce39b9b9d84b79130b71a44382284e1f5fd4190"><code>2ce39b9</code></a>
2.15.2</li>
<li><a
href="https://github.com/recharts/recharts/commit/27832326bd34d0309641fe1b08d6650c1f88318e"><code>2783232</code></a>
Fix activeBar Prop Not Working when tooltip shared is false (<a
href="https://redirect.github.com/recharts/recharts/issues/5718">#5718</a>)</li>
<li><a
href="https://github.com/recharts/recharts/commit/2b1afa75a93e218189bc79b22ba4467ec7e31277"><code>2b1afa7</code></a>
Add SVGElements to payload type (<a
href="https://redirect.github.com/recharts/recharts/issues/5712">#5712</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/recharts/recharts/compare/v2.15.0...v2.15.4">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=recharts&package-manager=npm_and_yarn&previous-version=2.15.0&new-version=2.15.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-01 11:26:26 +00:00
dependabot[bot] db22227f08 chore: bump cronstrue from 2.50.0 to 2.59.0 in /site (#20628)
Bumps [cronstrue](https://github.com/bradymholt/cronstrue) from 2.50.0
to 2.59.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/bradymholt/cronstrue/releases">cronstrue's
releases</a>.</em></p>
<blockquote>
<h2>v2.59.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix: Incorrect Multiple Range Hour Interpretation (<a
href="https://redirect.github.com/bradymholt/cronstrue/issues/294">#294</a>)
by <a href="https://github.com/wozaxi"><code>@​wozaxi</code></a> in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/345">bradymholt/cRonstrue#345</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/wozaxi"><code>@​wozaxi</code></a> made
their first contribution in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/345">bradymholt/cRonstrue#345</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bradymholt/cRonstrue/compare/v2.58.0...v2.59.0">https://github.com/bradymholt/cRonstrue/compare/v2.58.0...v2.59.0</a></p>
<h2>v2.58.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Avoid pluralized weekdays on danish translation by <a
href="https://github.com/rmja"><code>@​rmja</code></a> in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/344">bradymholt/cRonstrue#344</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bradymholt/cRonstrue/compare/v2.57.0...v2.58.0">https://github.com/bradymholt/cRonstrue/compare/v2.57.0...v2.58.0</a></p>
<h2>v2.57.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(playground): prevent page refresh on submit by <a
href="https://github.com/kricsleo"><code>@​kricsleo</code></a> in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/340">bradymholt/cRonstrue#340</a></li>
<li>Add workaround for french periods &amp; fix side effect with
previous change by <a
href="https://github.com/QuentiumYT"><code>@​QuentiumYT</code></a> in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/342">bradymholt/cRonstrue#342</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/kricsleo"><code>@​kricsleo</code></a>
made their first contribution in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/340">bradymholt/cRonstrue#340</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bradymholt/cRonstrue/compare/v2.56.0...v2.57.0">https://github.com/bradymholt/cRonstrue/compare/v2.56.0...v2.57.0</a></p>
<h2>v2.56.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Fix some french mistakes by <a
href="https://github.com/QuentiumYT"><code>@​QuentiumYT</code></a> in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/338">bradymholt/cRonstrue#338</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/QuentiumYT"><code>@​QuentiumYT</code></a> made
their first contribution in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/338">bradymholt/cRonstrue#338</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bradymholt/cRonstrue/compare/v2.55.0...v2.56.0">https://github.com/bradymholt/cRonstrue/compare/v2.55.0...v2.56.0</a></p>
<h2>v2.55.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump serialize-javascript and mocha by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/335">bradymholt/cRonstrue#335</a></li>
<li>Deprecate <code>tzOffset</code> option by <a
href="https://github.com/bradymholt"><code>@​bradymholt</code></a> in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/336">bradymholt/cRonstrue#336</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/bradymholt/cRonstrue/compare/v2.54.0...v2.55.0">https://github.com/bradymholt/cRonstrue/compare/v2.54.0...v2.55.0</a></p>
<h2>v2.54.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: correct norwegian translation of second by <a
href="https://github.com/frodeinglum"><code>@​frodeinglum</code></a> in
<a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/334">bradymholt/cRonstrue#334</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/frodeinglum"><code>@​frodeinglum</code></a>
made their first contribution in <a
href="https://redirect.github.com/bradymholt/cRonstrue/pull/334">bradymholt/cRonstrue#334</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/901f3d733d6d53cc85c1dfbdf7faa9ffa81f5145"><code>901f3d7</code></a>
Version 2.59.0</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/22152f3b57568ff2c4bbef9b0ef9c05dee13c9ae"><code>22152f3</code></a>
Fix: Incorrect Multiple Range Hour Interpretation (<a
href="https://redirect.github.com/bradymholt/cronstrue/issues/345">#345</a>)</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/40f75ac9d72c30a8d207e83157042995c4784c3e"><code>40f75ac</code></a>
Version 2.58.0</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/d4268ed6fcd120b04f3d37c313f4ebed60d62244"><code>d4268ed</code></a>
Avoid pluralized weekdays on danish translation (<a
href="https://redirect.github.com/bradymholt/cronstrue/issues/344">#344</a>)</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/72fe89b769a2ca189ab0dab8b69b48fc38ce5ed6"><code>72fe89b</code></a>
Version 2.57.0</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/0cf3a8cde40fd1384fc7e351795a1b8e3497ece1"><code>0cf3a8c</code></a>
Add workaround for french periods prefixes &amp; more choice tests (<a
href="https://redirect.github.com/bradymholt/cronstrue/issues/342">#342</a>)</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/885cd68808979a1d625b45fff62958b5268d2f78"><code>885cd68</code></a>
fix(playground): prevent page refresh on submit (<a
href="https://redirect.github.com/bradymholt/cronstrue/issues/340">#340</a>)</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/0830e5befdeace60b4f4dda649bfdc56a12e825f"><code>0830e5b</code></a>
Version 2.56.0</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/051f4319e5603c9fc076ccb51698fb2228010cb6"><code>051f431</code></a>
Fix some french mistakes (<a
href="https://redirect.github.com/bradymholt/cronstrue/issues/338">#338</a>)</li>
<li><a
href="https://github.com/bradymholt/cRonstrue/commit/3c09199ab19f87c197a72b39aad4f0e18992aaed"><code>3c09199</code></a>
Version 2.55.0</li>
<li>Additional commits viewable in <a
href="https://github.com/bradymholt/cronstrue/compare/v2.50.0...v2.59.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=cronstrue&package-manager=npm_and_yarn&previous-version=2.50.0&new-version=2.59.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-01 11:25:44 +00:00
dependabot[bot] 0eb8e904a1 chore: bump lucide-react from 0.545.0 to 0.552.0 in /site (#20625)
Bumps
[lucide-react](https://github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-react)
from 0.545.0 to 0.552.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.552.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(icons/file): arcified folds by <a
href="https://github.com/karsa-mistmere"><code>@​karsa-mistmere</code></a>
in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3587">lucide-icons/lucide#3587</a></li>
<li>feat(icons): added <code>solar-panel</code> icon by <a
href="https://github.com/UsamaKhan"><code>@​UsamaKhan</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/2780">lucide-icons/lucide#2780</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lucide-icons/lucide/compare/0.551.0...0.552.0">https://github.com/lucide-icons/lucide/compare/0.551.0...0.552.0</a></p>
<h2>Version 0.551.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat(icons): added <code>clock-check</code> icon by <a
href="https://github.com/jguddas"><code>@​jguddas</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/2402">lucide-icons/lucide#2402</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lucide-icons/lucide/compare/0.550.0...0.551.0">https://github.com/lucide-icons/lucide/compare/0.550.0...0.551.0</a></p>
<h2>Version 0.550.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat(icons): added <code>helicopter</code> icon by <a
href="https://github.com/liloudreams"><code>@​liloudreams</code></a> in
<a
href="https://redirect.github.com/lucide-icons/lucide/pull/2760">lucide-icons/lucide#2760</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a
href="https://github.com/liloudreams"><code>@​liloudreams</code></a>
made their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/2760">lucide-icons/lucide#2760</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lucide-icons/lucide/compare/0.549.0...0.550.0">https://github.com/lucide-icons/lucide/compare/0.549.0...0.550.0</a></p>
<h2>Version 0.549.0</h2>
<h2>What's Changed</h2>
<ul>
<li>fix(docs): Replace <code>pnpm install</code> with <code>pnpm
add</code> across documentation. by <a
href="https://github.com/josch87"><code>@​josch87</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3735">lucide-icons/lucide#3735</a></li>
<li>feat(docs): add new package for Go by <a
href="https://github.com/kaugesaar"><code>@​kaugesaar</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3736">lucide-icons/lucide#3736</a></li>
<li>feat(icons): added <code>git-branch-minus</code> icon by <a
href="https://github.com/joris-gallot"><code>@​joris-gallot</code></a>
in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3586">lucide-icons/lucide#3586</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/josch87"><code>@​josch87</code></a> made
their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3735">lucide-icons/lucide#3735</a></li>
<li><a href="https://github.com/kaugesaar"><code>@​kaugesaar</code></a>
made their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3736">lucide-icons/lucide#3736</a></li>
<li><a
href="https://github.com/joris-gallot"><code>@​joris-gallot</code></a>
made their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3586">lucide-icons/lucide#3586</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lucide-icons/lucide/compare/0.548.0...0.549.0">https://github.com/lucide-icons/lucide/compare/0.548.0...0.549.0</a></p>
<h2>Version 0.548.0</h2>
<h2>What's Changed</h2>
<ul>
<li>feat(docs): add new package for Slint by <a
href="https://github.com/cnlancehu"><code>@​cnlancehu</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3698">lucide-icons/lucide#3698</a></li>
<li>docs(site): add introductions for packages in documentation by <a
href="https://github.com/mattheskaiser"><code>@​mattheskaiser</code></a>
in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3643">lucide-icons/lucide#3643</a></li>
<li>Fix default prop by <a
href="https://github.com/ericfennis"><code>@​ericfennis</code></a> in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3730">lucide-icons/lucide#3730</a></li>
<li>feat(icons): added <code>gamepad-directional</code> icon by <a
href="https://github.com/felipeajzanetti"><code>@​felipeajzanetti</code></a>
in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3693">lucide-icons/lucide#3693</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/cnlancehu"><code>@​cnlancehu</code></a>
made their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3698">lucide-icons/lucide#3698</a></li>
<li><a
href="https://github.com/mattheskaiser"><code>@​mattheskaiser</code></a>
made their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3643">lucide-icons/lucide#3643</a></li>
<li><a
href="https://github.com/felipeajzanetti"><code>@​felipeajzanetti</code></a>
made their first contribution in <a
href="https://redirect.github.com/lucide-icons/lucide/pull/3693">lucide-icons/lucide#3693</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/lucide-icons/lucide/compare/0.547.0...0.548.0">https://github.com/lucide-icons/lucide/compare/0.547.0...0.548.0</a></p>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/lucide-icons/lucide/commits/0.552.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.545.0&new-version=0.552.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-01 11:24:03 +00:00
dependabot[bot] 2734123ac2 chore: bump axios from 1.12.0 to 1.13.1 in /site (#20623)
Bumps [axios](https://github.com/axios/axios) from 1.12.0 to 1.13.1.
<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.1</h2>
<h2>Release notes:</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>http:</strong> fixed a regression that caused the data
stream to be interrupted for responses with non-OK HTTP statuses; (<a
href="https://redirect.github.com/axios/axios/issues/7193">#7193</a>)
(<a
href="https://github.com/axios/axios/commit/bcd5581d208cd372055afdcb2fd10b68ca40613c">bcd5581</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a href="https://github.com/imanchalsingh"
title="+220/-111 ([#7173](https://github.com/axios/axios/issues/7173)
)">Anchal Singh</a></li>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+18/-1
([#7193](https://github.com/axios/axios/issues/7193) )">Dmitriy
Mozgovoy</a></li>
</ul>
<h2>Release v1.13.0</h2>
<h2>Release notes:</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>fetch:</strong> prevent TypeError when config.env is
undefined (<a
href="https://redirect.github.com/axios/axios/issues/7155">#7155</a>)
(<a
href="https://github.com/axios/axios/commit/015faeca9f26db76f9562760f04bb9f8229f4db1">015faec</a>)</li>
<li>resolve issue <a
href="https://redirect.github.com/axios/axios/issues/7131">#7131</a>
(added spacing in mergeConfig.js) (<a
href="https://redirect.github.com/axios/axios/issues/7133">#7133</a>)
(<a
href="https://github.com/axios/axios/commit/9b9ec98548d93e9f2204deea10a5f1528bf3ce62">9b9ec98</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>http:</strong> add HTTP2 support; (<a
href="https://redirect.github.com/axios/axios/issues/7150">#7150</a>)
(<a
href="https://github.com/axios/axios/commit/d676df772244726533ca320f42e967f5af056bac">d676df7</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+794/-180
([#7186](https://github.com/axios/axios/issues/7186)
[#7150](https://github.com/axios/axios/issues/7150)
[#7039](https://github.com/axios/axios/issues/7039) )">Dmitriy
Mozgovoy</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/noritaka1166"
title="+24/-509 ([#7032](https://github.com/axios/axios/issues/7032)
)">Noritaka Kobayashi</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Aviraj2929"
title="+211/-93 ([#7136](https://github.com/axios/axios/issues/7136)
[#7135](https://github.com/axios/axios/issues/7135)
[#7134](https://github.com/axios/axios/issues/7134)
[#7112](https://github.com/axios/axios/issues/7112)
)">Aviraj2929</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Prasoon52"
title="+167/-6 ([#7099](https://github.com/axios/axios/issues/7099)
)">prasoon patel</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Samy-in"
title="+134/-0 ([#7171](https://github.com/axios/axios/issues/7171)
)">Samyak Dandge</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/imanchalsingh"
title="+53/-56 ([#7170](https://github.com/axios/axios/issues/7170)
)">Anchal Singh</a></li>
<li><!-- raw HTML omitted --> <a
href="https://github.com/jaiyankargupta" title="+28/-28
([#7073](https://github.com/axios/axios/issues/7073) )">Rahul
Kumar</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Amitverma0509"
title="+24/-13 ([#7129](https://github.com/axios/axios/issues/7129)
)">Amit Verma</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/abhishekmaniy"
title="+23/-4 ([#7119](https://github.com/axios/axios/issues/7119)
[#7117](https://github.com/axios/axios/issues/7117)
[#7116](https://github.com/axios/axios/issues/7116)
[#7115](https://github.com/axios/axios/issues/7115)
)">Abhishek3880</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Dhvani365"
title="+14/-5 ([#7175](https://github.com/axios/axios/issues/7175)
)">Dhvani Maktuporia</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/sam3690"
title="+4/-4 ([#7133](https://github.com/axios/axios/issues/7133)
)">Usama Ayoub</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/ikuy1203"
title="+3/-3 ([#7166](https://github.com/axios/axios/issues/7166)
)">ikuy1203</a></li>
<li><!-- raw HTML omitted --> <a
href="https://github.com/Kirito-Excalibur" title="+1/-1
([#7172](https://github.com/axios/axios/issues/7172) )">Nikhil Simon
Toppo</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Wangarijane"
title="+1/-1 ([#7155](https://github.com/axios/axios/issues/7155)
)">Jane Wangari</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Supakornn"
title="+1/-1 ([#7065](https://github.com/axios/axios/issues/7065)
)">Supakorn Ieamgomol</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/kianmeng"
title="+1/-1 ([#7046](https://github.com/axios/axios/issues/7046)
)">Kian-Meng Ang</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/k-utsumi"
title="+1/-1 ([#7037](https://github.com/axios/axios/issues/7037)
)">UTSUMI Keiji</a></li>
</ul>
<h2>Release v1.12.2</h2>
<h2>Release notes:</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>fetch:</strong> use current global fetch instead of cached
one when env fetch is not specified to keep MSW support; (<a
href="https://redirect.github.com/axios/axios/issues/7030">#7030</a>)
(<a
href="https://github.com/axios/axios/commit/cf78825e1229b60d1629ad0bbc8a752ff43c3f53">cf78825</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</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.0...v1.13.1">1.13.1</a>
(2025-10-28)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>http:</strong> fixed a regression that caused the data
stream to be interrupted for responses with non-OK HTTP statuses; (<a
href="https://redirect.github.com/axios/axios/issues/7193">#7193</a>)
(<a
href="https://github.com/axios/axios/commit/bcd5581d208cd372055afdcb2fd10b68ca40613c">bcd5581</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a href="https://github.com/imanchalsingh"
title="+220/-111 ([#7173](https://github.com/axios/axios/issues/7173)
)">Anchal Singh</a></li>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+18/-1
([#7193](https://github.com/axios/axios/issues/7193) )">Dmitriy
Mozgovoy</a></li>
</ul>
<h1><a
href="https://github.com/axios/axios/compare/v1.12.2...v1.13.0">1.13.0</a>
(2025-10-27)</h1>
<h3>Bug Fixes</h3>
<ul>
<li><strong>fetch:</strong> prevent TypeError when config.env is
undefined (<a
href="https://redirect.github.com/axios/axios/issues/7155">#7155</a>)
(<a
href="https://github.com/axios/axios/commit/015faeca9f26db76f9562760f04bb9f8229f4db1">015faec</a>)</li>
<li>resolve issue <a
href="https://redirect.github.com/axios/axios/issues/7131">#7131</a>
(added spacing in mergeConfig.js) (<a
href="https://redirect.github.com/axios/axios/issues/7133">#7133</a>)
(<a
href="https://github.com/axios/axios/commit/9b9ec98548d93e9f2204deea10a5f1528bf3ce62">9b9ec98</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>http:</strong> add HTTP2 support; (<a
href="https://redirect.github.com/axios/axios/issues/7150">#7150</a>)
(<a
href="https://github.com/axios/axios/commit/d676df772244726533ca320f42e967f5af056bac">d676df7</a>)</li>
</ul>
<h3>Contributors to this release</h3>
<ul>
<li><!-- raw HTML omitted --> <a
href="https://github.com/DigitalBrainJS" title="+794/-180
([#7186](https://github.com/axios/axios/issues/7186)
[#7150](https://github.com/axios/axios/issues/7150)
[#7039](https://github.com/axios/axios/issues/7039) )">Dmitriy
Mozgovoy</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/noritaka1166"
title="+24/-509 ([#7032](https://github.com/axios/axios/issues/7032)
)">Noritaka Kobayashi</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Aviraj2929"
title="+211/-93 ([#7136](https://github.com/axios/axios/issues/7136)
[#7135](https://github.com/axios/axios/issues/7135)
[#7134](https://github.com/axios/axios/issues/7134)
[#7112](https://github.com/axios/axios/issues/7112)
)">Aviraj2929</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Prasoon52"
title="+167/-6 ([#7099](https://github.com/axios/axios/issues/7099)
)">prasoon patel</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Samy-in"
title="+134/-0 ([#7171](https://github.com/axios/axios/issues/7171)
)">Samyak Dandge</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/imanchalsingh"
title="+53/-56 ([#7170](https://github.com/axios/axios/issues/7170)
)">Anchal Singh</a></li>
<li><!-- raw HTML omitted --> <a
href="https://github.com/jaiyankargupta" title="+28/-28
([#7073](https://github.com/axios/axios/issues/7073) )">Rahul
Kumar</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Amitverma0509"
title="+24/-13 ([#7129](https://github.com/axios/axios/issues/7129)
)">Amit Verma</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/abhishekmaniy"
title="+23/-4 ([#7119](https://github.com/axios/axios/issues/7119)
[#7117](https://github.com/axios/axios/issues/7117)
[#7116](https://github.com/axios/axios/issues/7116)
[#7115](https://github.com/axios/axios/issues/7115)
)">Abhishek3880</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Dhvani365"
title="+14/-5 ([#7175](https://github.com/axios/axios/issues/7175)
)">Dhvani Maktuporia</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/sam3690"
title="+4/-4 ([#7133](https://github.com/axios/axios/issues/7133)
)">Usama Ayoub</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/ikuy1203"
title="+3/-3 ([#7166](https://github.com/axios/axios/issues/7166)
)">ikuy1203</a></li>
<li><!-- raw HTML omitted --> <a
href="https://github.com/Kirito-Excalibur" title="+1/-1
([#7172](https://github.com/axios/axios/issues/7172) )">Nikhil Simon
Toppo</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Wangarijane"
title="+1/-1 ([#7155](https://github.com/axios/axios/issues/7155)
)">Jane Wangari</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/Supakornn"
title="+1/-1 ([#7065](https://github.com/axios/axios/issues/7065)
)">Supakorn Ieamgomol</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/kianmeng"
title="+1/-1 ([#7046](https://github.com/axios/axios/issues/7046)
)">Kian-Meng Ang</a></li>
<li><!-- raw HTML omitted --> <a href="https://github.com/k-utsumi"
title="+1/-1 ([#7037](https://github.com/axios/axios/issues/7037)
)">UTSUMI Keiji</a></li>
</ul>
<h2><a
href="https://github.com/axios/axios/compare/v1.12.1...v1.12.2">1.12.2</a>
(2025-09-14)</h2>
<h3>Bug Fixes</h3>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/axios/axios/commit/1ef8e7218b085ac28b675b07349c6d7906a7b6ac"><code>1ef8e72</code></a>
chore(release): v1.13.1 (<a
href="https://redirect.github.com/axios/axios/issues/7194">#7194</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/bcd5581d208cd372055afdcb2fd10b68ca40613c"><code>bcd5581</code></a>
fix(http): fixed a regression that caused the data stream to be
interrupted f...</li>
<li><a
href="https://github.com/axios/axios/commit/c9b33712aac00ca6da7e9767426ff2e0a36c7eed"><code>c9b3371</code></a>
chore: enhance styling and responsiveness in client.html (<a
href="https://redirect.github.com/axios/axios/issues/7173">#7173</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/9ead04d8abbcd53718dbc31b1250ea74300921c8"><code>9ead04d</code></a>
[Release] v1.13.0 (<a
href="https://redirect.github.com/axios/axios/issues/7189">#7189</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/d000fbfd0722a9c3bd0bcea3451c6d515813635d"><code>d000fbf</code></a>
fix(http2): fix possible race condition when handling http2 stream on
almost ...</li>
<li><a
href="https://github.com/axios/axios/commit/08db960d9f1003b3c561026f636df2d6d5d8ca57"><code>08db960</code></a>
docs: added example for improved network error handling (with
Wrapper/Middlew...</li>
<li><a
href="https://github.com/axios/axios/commit/46e1981d0ff2c6aec794fe3425d031495bc00931"><code>46e1981</code></a>
refactor: form data handling in index.html (<a
href="https://redirect.github.com/axios/axios/issues/7170">#7170</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/889f8ef8be025c5c580594f0b631daf50a2d3405"><code>889f8ef</code></a>
docs: fix mismatched return type (<a
href="https://redirect.github.com/axios/axios/issues/7172">#7172</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/7b197ef6ce8e448e6b748749055269e97b10d009"><code>7b197ef</code></a>
fix: sandbox ui updated (<a
href="https://redirect.github.com/axios/axios/issues/7175">#7175</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/6dff629ee78646c92739bf39927d9145906cd430"><code>6dff629</code></a>
chore: fix typos in examples (<a
href="https://redirect.github.com/axios/axios/issues/7166">#7166</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/axios/axios/compare/v1.12.0...v1.13.1">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.12.0&new-version=1.13.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-11-01 11:23:39 +00:00
dependabot[bot] 37432aefa6 chore: bump rxjs from 7.8.1 to 7.8.2 in /site (#20622)
Bumps [rxjs](https://github.com/reactivex/rxjs) from 7.8.1 to 7.8.2.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ReactiveX/rxjs/blob/7.8.2/CHANGELOG.md">rxjs's
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/reactivex/rxjs/compare/7.8.1...7.8.2">7.8.2</a>
(2025-02-22)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>animationFrameScheduler:</strong> some tasks are never
flushed and sometimes it breaks completely (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7444">#7444</a>)
(<a
href="https://github.com/reactivex/rxjs/commit/8bbfa4efd15f6572316d5b2b05b2f49ded69a3ca">8bbfa4e</a>)</li>
<li><strong>mergeWith:</strong> works correctly with an Array (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7281">#7281</a>)
(<a
href="https://github.com/reactivex/rxjs/commit/27855c635ca74107352ae3336944433a328c0b41">27855c6</a>)</li>
<li><strong>subscriber:</strong> strict type signature for next method
(<a
href="https://redirect.github.com/reactivex/rxjs/issues/7172">#7172</a>)
(<a
href="https://github.com/reactivex/rxjs/commit/0e2ef5e1142699b028bc3624aae9b24c3e3aaccf">0e2ef5e</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/e5351d02e225e275ac0e497c7b66eaa5f0c88791"><code>e5351d0</code></a>
chore(publish): 7.8.2</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/8bbfa4efd15f6572316d5b2b05b2f49ded69a3ca"><code>8bbfa4e</code></a>
fix(animationFrameScheduler): some tasks are never flushed and sometimes
it b...</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/4a2d0d29a7b17607e74afcb6fb8037fe58ef9021"><code>4a2d0d2</code></a>
docs(rxjs.dex): replace polyfill.io with a Cloudflare equivalent (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7487">#7487</a>)</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/2fb074008430c8fcae9a10c22a3cd7b5140ffd84"><code>2fb0740</code></a>
chore: 7.x remove global npm install and ignore latest TS (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7398">#7398</a>)</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/d69d890b65c2890c1bd7cd181cb462848f8b75fb"><code>d69d890</code></a>
docs: fix missing overloads in docs when overload count is less than 3
(<a
href="https://redirect.github.com/reactivex/rxjs/issues/7367">#7367</a>...</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/27855c635ca74107352ae3336944433a328c0b41"><code>27855c6</code></a>
fix(mergeWith): works correctly with an Array (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7281">#7281</a>)</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/9db65635b0b26b25c35b3470885c6f02abd54122"><code>9db6563</code></a>
docs: provide URL for the V8 docs app (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7244">#7244</a>)</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/5c3fb3347376eaa079655fc70f6d39fbbd7ca180"><code>5c3fb33</code></a>
docs: add MonoTypeOperatorFunction documentation (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7284">#7284</a>)</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/0e2ef5e1142699b028bc3624aae9b24c3e3aaccf"><code>0e2ef5e</code></a>
fix(subscriber): strict type signature for next method (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7172">#7172</a>)</li>
<li><a
href="https://github.com/ReactiveX/rxjs/commit/b6d00c1d276ad3b987dd832168448e106741ebda"><code>b6d00c1</code></a>
docs: improve glossary and semantics page (<a
href="https://redirect.github.com/reactivex/rxjs/issues/7267">#7267</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/reactivex/rxjs/compare/7.8.1...7.8.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=rxjs&package-manager=npm_and_yarn&previous-version=7.8.1&new-version=7.8.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-11-01 11:23:12 +00:00
dependabot[bot] cf746f3a87 chore: bump @fontsource/jetbrains-mono from 5.2.5 to 5.2.8 in /site (#20621)
Bumps
[@fontsource/jetbrains-mono](https://github.com/fontsource/font-files/tree/HEAD/fonts/google/jetbrains-mono)
from 5.2.5 to 5.2.8.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/fontsource/font-files/commits/HEAD/fonts/google/jetbrains-mono">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@fontsource/jetbrains-mono&package-manager=npm_and_yarn&previous-version=5.2.5&new-version=5.2.8)](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-01 11:22:26 +00:00
dependabot[bot] ea533aa522 chore: bump @octokit/types from 12.3.0 to 12.6.0 in /site (#20619)
Bumps [@octokit/types](https://github.com/octokit/types.ts) from 12.3.0
to 12.6.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/octokit/types.ts/releases"><code>@​octokit/types</code>'s
releases</a>.</em></p>
<blockquote>
<h2>v12.6.0</h2>
<h1><a
href="https://github.com/octokit/types.ts/compare/v12.5.0...v12.6.0">12.6.0</a>
(2024-02-22)</h1>
<h3>Features</h3>
<ul>
<li>many new endpoints (<a
href="https://redirect.github.com/octokit/types.ts/issues/618">#618</a>)
(<a
href="https://github.com/octokit/types.ts/commit/b2d7de9e6f2fd2d8f82a463cee6c324edf941607">b2d7de9</a>)</li>
</ul>
<h2>v12.5.0</h2>
<h1><a
href="https://github.com/octokit/types.ts/compare/v12.4.0...v12.5.0">12.5.0</a>
(2024-02-15)</h1>
<h3>Features</h3>
<ul>
<li>add x-accepted-github-permissions (<a
href="https://redirect.github.com/octokit/types.ts/issues/609">#609</a>)
(<a
href="https://github.com/octokit/types.ts/commit/bc28bdc744c65487061eae4227a8da33c15a2468">bc28bdc</a>)</li>
</ul>
<h2>v12.4.0</h2>
<h1><a
href="https://github.com/octokit/types.ts/compare/v12.3.0...v12.4.0">12.4.0</a>
(2023-12-04)</h1>
<h3>Features</h3>
<ul>
<li>permissions.organization_custom_properties (<a
href="https://redirect.github.com/octokit/types.ts/issues/598">#598</a>)
(<a
href="https://github.com/octokit/types.ts/commit/ff984680c4b149e22c7ede4a6ee3d73aa299471b">ff98468</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/octokit/types.ts/commit/b2d7de9e6f2fd2d8f82a463cee6c324edf941607"><code>b2d7de9</code></a>
feat: many new endpoints (<a
href="https://redirect.github.com/octokit/types.ts/issues/618">#618</a>)</li>
<li><a
href="https://github.com/octokit/types.ts/commit/bc28bdc744c65487061eae4227a8da33c15a2468"><code>bc28bdc</code></a>
feat: add x-accepted-github-permissions (<a
href="https://redirect.github.com/octokit/types.ts/issues/609">#609</a>)</li>
<li><a
href="https://github.com/octokit/types.ts/commit/fa1e25b6351b4b057f6c8a41e38121622e0beccf"><code>fa1e25b</code></a>
chore(deps): update dependency npm-run-all2 to v6</li>
<li><a
href="https://github.com/octokit/types.ts/commit/349bf948b7a45b70ea7ddbc31fba08acd8fc42ad"><code>349bf94</code></a>
chore(deps): replace dependency npm-run-all with npm-run-all2
^5.0.0</li>
<li><a
href="https://github.com/octokit/types.ts/commit/47eb4d05c5f3a13fffe6449b57bd1229d28081f7"><code>47eb4d0</code></a>
ci(action): update peter-evans/create-or-update-comment action to
v4</li>
<li><a
href="https://github.com/octokit/types.ts/commit/7e554cd03ad7967ac235748b2a2108ab67a0782a"><code>7e554cd</code></a>
chore(deps): update dependency semantic-release to v23</li>
<li><a
href="https://github.com/octokit/types.ts/commit/40bc39f7df62a2e8c7bdbac810cc4549189ab2d2"><code>40bc39f</code></a>
ci(action): update github/codeql-action action to v3</li>
<li><a
href="https://github.com/octokit/types.ts/commit/dbc66ecf548e1feb28f9b95cff8cefed296e6694"><code>dbc66ec</code></a>
🚧 Workflows have changed (<a
href="https://redirect.github.com/octokit/types.ts/issues/600">#600</a>)</li>
<li><a
href="https://github.com/octokit/types.ts/commit/ff984680c4b149e22c7ede4a6ee3d73aa299471b"><code>ff98468</code></a>
feat: permissions.organization_custom_properties (<a
href="https://redirect.github.com/octokit/types.ts/issues/598">#598</a>)</li>
<li><a
href="https://github.com/octokit/types.ts/commit/1397259ee01cfc5e5110818ce40c8ed1a59e1f45"><code>1397259</code></a>
build(deps): lock file maintenance</li>
<li>Additional commits viewable in <a
href="https://github.com/octokit/types.ts/compare/v12.3.0...v12.6.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@octokit/types&package-manager=npm_and_yarn&previous-version=12.3.0&new-version=12.6.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-01 11:21:47 +00:00
dependabot[bot] 979df63788 chore: bump the vite group across 1 directory with 3 updates (#20616)
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.0.4 to 5.1.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitejs/vite-plugin-react/releases"><code>@​vitejs/plugin-react</code>'s
releases</a>.</em></p>
<blockquote>
<h2>plugin-react@5.1.0</h2>
<h3>Add <code>@vitejs/plugin-react/preamble</code> virtual module for
SSR HMR (<a
href="https://redirect.github.com/vitejs/vite-plugin-react/pull/890">#890</a>)</h3>
<p>SSR applications can now initialize HMR runtime by importing
<code>@vitejs/plugin-react/preamble</code> at the top of their client
entry instead of manually calling <code>transformIndexHtml</code>. This
simplifies SSR setup for applications that don't use the
<code>transformIndexHtml</code> API.</p>
<h3>Fix raw Rolldown support for Rolldown 1.0.0-beta.44+ (<a
href="https://redirect.github.com/vitejs/vite-plugin-react/pull/930">#930</a>)</h3>
<p>Rolldown 1.0.0-beta.44+ removed the top-level <code>jsx</code> option
in favor of <code>transform.jsx</code>. This plugin now uses the
<code>transform.jsx</code> option to support Rolldown
1.0.0-beta.44+.</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.0 (2025-10-24)</h2>
<h3>Add <code>@vitejs/plugin-react/preamble</code> virtual module for
SSR HMR (<a
href="https://redirect.github.com/vitejs/vite-plugin-react/pull/890">#890</a>)</h3>
<p>SSR applications can now initialize HMR runtime by importing
<code>@vitejs/plugin-react/preamble</code> at the top of their client
entry instead of manually calling <code>transformIndexHtml</code>. This
simplifies SSR setup for applications that don't use the
<code>transformIndexHtml</code> API.</p>
<h3>Fix raw Rolldown support for Rolldown 1.0.0-beta.44+ (<a
href="https://redirect.github.com/vitejs/vite-plugin-react/pull/930">#930</a>)</h3>
<p>Rolldown 1.0.0-beta.44+ removed the top-level <code>jsx</code> option
in favor of <code>transform.jsx</code>. This plugin now uses the
<code>transform.jsx</code> option to support Rolldown
1.0.0-beta.44+.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/3e5a3742e94be975cbcec230fbab5e801b80dc5b"><code>3e5a374</code></a>
release: plugin-react@5.1.0</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/44cbed4d00d48331d9757085fae79807dc1a3969"><code>44cbed4</code></a>
fix(react): compat with newer rolldown (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/930">#930</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/c54d3c69983695785c90998760d0ec879c84dd33"><code>c54d3c6</code></a>
chore(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/926">#926</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/a2d76d94768fa6ec33d8045ea51a1f6aa6026da2"><code>a2d76d9</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/918">#918</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/fffb7eb7a4d939783d1da09e2ca6368382735ca3"><code>fffb7eb</code></a>
feat(react): expose virtual module to simplify hmr preamble setup on ssr
(<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/890">#890</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/b79592a72add1806162afe553d79a5eae23252bd"><code>b79592a</code></a>
fix(deps): update react-related dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/901">#901</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/2d239fc8dec2ab499282eaea45b2bffb8d182f26"><code>2d239fc</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/896">#896</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/73be2f0bbf23f1624cfbf9a1743d9f42ae1ffd10"><code>73be2f0</code></a>
chore(deps): fix vitest &gt; rolldown-vite dependency (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/889">#889</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/407795dbd0129b069cf3ac842846687485a5ef00"><code>407795d</code></a>
fix(deps): update all non-major dependencies (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/887">#887</a>)</li>
<li><a
href="https://github.com/vitejs/vite-plugin-react/commit/47db4734d5ceb65039ba320ef914775f8960c0d8"><code>47db473</code></a>
chore(react): fix ecosystem-ci failure (<a
href="https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react/issues/888">#888</a>)</li>
<li>See full diff in <a
href="https://github.com/vitejs/vite-plugin-react/commits/plugin-react@5.1.0/packages/plugin-react">compare
view</a></li>
</ul>
</details>
<br />

Updates `vite` from 7.1.11 to 7.1.12
<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.1.12</h2>
<p>Please refer to <a
href="https://github.com/vitejs/vite/blob/v7.1.12/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/v7.1.12/packages/vite/CHANGELOG.md">vite's
changelog</a>.</em></p>
<blockquote>
<h2><!-- raw HTML omitted --><a
href="https://github.com/vitejs/vite/compare/v7.1.11...v7.1.12">7.1.12</a>
(2025-10-23)<!-- raw HTML omitted --></h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>deps:</strong> downgrade commonjs plugin to 28.0.6 to avoid
rollup/plugins<a
href="https://redirect.github.com/vitejs/vite/issues/1909">#1909</a> (<a
href="https://redirect.github.com/vitejs/vite/issues/20990">#20990</a>)
(<a
href="https://github.com/vitejs/vite/commit/56fd7224aa3163fffe1924738aff33f778245901">56fd722</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitejs/vite/commit/2436afef044d90f710fdfd714488a71efdd29092"><code>2436afe</code></a>
release: v7.1.12</li>
<li><a
href="https://github.com/vitejs/vite/commit/56fd7224aa3163fffe1924738aff33f778245901"><code>56fd722</code></a>
fix(deps): downgrade commonjs plugin to 28.0.6 to avoid <a
href="https://redirect.github.com/rollup/plugins/issues/1909">rollup/plugins#1909</a>
(...</li>
<li>See full diff in <a
href="https://github.com/vitejs/vite/commits/v7.1.12/packages/vite">compare
view</a></li>
</ul>
</details>
<br />

Updates `vitest` from 4.0.5 to 4.0.6
<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.6</h2>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li>Don't merge errors with different diffs for reporting  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/8871">vitest-dev/vitest#8871</a>
<a href="https://github.com/vitest-dev/vitest/commit/3e19f27d0"><!-- raw
HTML omitted -->(3e19f)<!-- raw HTML omitted --></a></li>
<li>Do not throw when importing a type from an external package  -  by
<a href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a>
in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/8875">vitest-dev/vitest#8875</a>
<a href="https://github.com/vitest-dev/vitest/commit/7e6c37ae5"><!-- raw
HTML omitted -->(7e6c3)<!-- raw HTML omitted --></a></li>
<li>Improve spying types  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/8878">vitest-dev/vitest#8878</a>
<a href="https://github.com/vitest-dev/vitest/commit/ca041f51a"><!-- raw
HTML omitted -->(ca041)<!-- raw HTML omitted --></a></li>
<li>Reuse the same environment when <code>isolate</code> and
<code>fileParallelism</code> are false  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/8889">vitest-dev/vitest#8889</a>
<a href="https://github.com/vitest-dev/vitest/commit/31706dfe5"><!-- raw
HTML omitted -->(31706)<!-- raw HTML omitted --></a></li>
<li><strong>browser</strong>:
<ul>
<li>Support module tracking  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/8877">vitest-dev/vitest#8877</a>
<a href="https://github.com/vitest-dev/vitest/commit/9e24a59f2"><!-- raw
HTML omitted -->(9e24a)<!-- raw HTML omitted --></a></li>
<li>Ensure setup files are re-evaluated on each test run  -  by <a
href="https://github.com/yjaaidi"><code>@​yjaaidi</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/8883">vitest-dev/vitest#8883</a>
and <a
href="https://redirect.github.com/vitest-dev/vitest/issues/8884">vitest-dev/vitest#8884</a>
<a href="https://github.com/vitest-dev/vitest/commit/f50ea7a25"><!-- raw
HTML omitted -->(f50ea)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>coverage</strong>:
<ul>
<li>Prevent filtering out virtual files before remapping to sources  - 
by <a href="https://github.com/AriPerkkio"><code>@​AriPerkkio</code></a>
in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/8860">vitest-dev/vitest#8860</a>
<a href="https://github.com/vitest-dev/vitest/commit/e3b777550"><!-- raw
HTML omitted -->(e3b77)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>happy-dom</strong>:
<ul>
<li>Properly teardown additional keys  -  by <a
href="https://github.com/sheremet-va"><code>@​sheremet-va</code></a> in
<a
href="https://redirect.github.com/vitest-dev/vitest/issues/8888">vitest-dev/vitest#8888</a>
<a href="https://github.com/vitest-dev/vitest/commit/10a06d8c9"><!-- raw
HTML omitted -->(10a06)<!-- raw HTML omitted --></a></li>
</ul>
</li>
<li><strong>jsdom</strong>:
<ul>
<li>Pass down Node.js <code>FormData</code> to <code>Request</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/8880">vitest-dev/vitest#8880</a>
<a href="https://github.com/vitest-dev/vitest/commit/197caf2f9"><!-- raw
HTML omitted -->(197ca)<!-- raw HTML omitted --></a></li>
</ul>
</li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.0.5...v4.0.6">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitest-dev/vitest/commit/2e7b2b8b98dafc047a3bf2fc0422076ca5e346fa"><code>2e7b2b8</code></a>
chore: release v4.0.6</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/31706dfe519bd837db7a18da0e8e44ee3ffef1f3"><code>31706df</code></a>
fix: reuse the same environment when <code>isolate</code> and
<code>fileParallelism</code> are fals...</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/10a06d8c9238856b921131c725f6e21d6c98697e"><code>10a06d8</code></a>
fix(happy-dom): properly teardown additional keys (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/8888">#8888</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/197caf2f94e249566c0d168ccf4a3ed9b14dd02a"><code>197caf2</code></a>
fix(jsdom): pass down Node.js <code>FormData</code> to
<code>Request</code> (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/8880">#8880</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/ca041f51ad2395dd91d18c33b642fb346c6bfd15"><code>ca041f5</code></a>
fix: improve spying types (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/8878">#8878</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/e3b7775509dde217436b455d9d3ebcd11e21e7e3"><code>e3b7775</code></a>
fix(coverage): prevent filtering out virtual files before remapping to
source...</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/7e6c37ae5f1935d16be37e9885427b7010efe164"><code>7e6c37a</code></a>
fix: do not throw when importing a type from an external package (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/8875">#8875</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/3e19f27d03c324ef9111c4e40e7b04e08498fa16"><code>3e19f27</code></a>
fix: don't merge errors with different diffs for reporting (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/8871">#8871</a>)</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.0.6/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-11-01 11:20:41 +00:00
dependabot[bot] c4e9749146 chore: bump the radix group across 1 directory with 12 updates (#20614)
Bumps the radix group with 12 updates in the /site directory:

| Package | From | To |
| --- | --- | --- |
| [@radix-ui/react-avatar](https://github.com/radix-ui/primitives) |
`1.1.2` | `1.1.10` |
| [@radix-ui/react-checkbox](https://github.com/radix-ui/primitives) |
`1.1.4` | `1.3.3` |
| [@radix-ui/react-collapsible](https://github.com/radix-ui/primitives)
| `1.1.2` | `1.1.12` |
| [@radix-ui/react-dialog](https://github.com/radix-ui/primitives) |
`1.1.4` | `1.1.15` |
|
[@radix-ui/react-dropdown-menu](https://github.com/radix-ui/primitives)
| `2.1.4` | `2.1.16` |
| [@radix-ui/react-label](https://github.com/radix-ui/primitives) |
`2.1.0` | `2.1.7` |
| [@radix-ui/react-popover](https://github.com/radix-ui/primitives) |
`1.1.5` | `1.1.15` |
| [@radix-ui/react-radio-group](https://github.com/radix-ui/primitives)
| `1.2.3` | `1.3.8` |
| [@radix-ui/react-scroll-area](https://github.com/radix-ui/primitives)
| `1.2.3` | `1.2.10` |
| [@radix-ui/react-slider](https://github.com/radix-ui/primitives) |
`1.2.2` | `1.3.6` |
| [@radix-ui/react-switch](https://github.com/radix-ui/primitives) |
`1.1.1` | `1.2.6` |
| [@radix-ui/react-tooltip](https://github.com/radix-ui/primitives) |
`1.1.7` | `1.2.8` |


Updates `@radix-ui/react-avatar` from 1.1.2 to 1.1.10
<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-checkbox` from 1.1.4 to 1.3.3
<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-collapsible` from 1.1.2 to 1.1.12
<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-dialog` from 1.1.4 to 1.1.15
<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-dropdown-menu` from 2.1.4 to 2.1.16
<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.0 to 2.1.7
<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>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~chancestrickland">chancestrickland</a>, a
new releaser for <code>@​radix-ui/react-label</code> since your current
version.</p>
</details>
<br />

Updates `@radix-ui/react-popover` from 1.1.5 to 1.1.15
<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-radio-group` from 1.2.3 to 1.3.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-scroll-area` from 1.2.3 to 1.2.10
<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-slider` from 1.2.2 to 1.3.6
<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-switch` from 1.1.1 to 1.2.6
<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-tooltip` from 1.1.7 to 1.2.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 />


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-11-01 11:18:46 +00:00
dependabot[bot] fb785d3524 chore: bump next from 15.5.4 to 15.5.6 in /offlinedocs (#20618)
Bumps [next](https://github.com/vercel/next.js) from 15.5.4 to 15.5.6.
<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.6</h2>
<blockquote>
<p>[!NOTE]<br />
This release is backporting bug fixes. It does <strong>not</strong>
include all pending features/changes on canary.</p>
</blockquote>
<h3>Core Changes</h3>
<ul>
<li>Turbopack: don't define process.cwd() in node_modules <a
href="https://redirect.github.com/vercel/next.js/issues/83452">#83452</a></li>
</ul>
<h3>Credits</h3>
<p>Huge thanks to <a
href="https://github.com/mischnic"><code>@​mischnic</code></a> for
helping!</p>
<h2>v15.5.5</h2>
<blockquote>
<p>[!NOTE]<br />
This release is backporting bug fixes. It does <strong>not</strong>
include all pending features/changes on canary.</p>
</blockquote>
<h3>Core Changes</h3>
<ul>
<li>Split code-frame into separate compiled package (<a
href="https://redirect.github.com/vercel/next.js/issues/84238">#84238</a>)</li>
<li>Add deprecation warning to Runtime config (<a
href="https://redirect.github.com/vercel/next.js/issues/84650">#84650</a>)</li>
<li>fix: unstable_cache should perform blocking revalidation during ISR
revalidation (<a
href="https://redirect.github.com/vercel/next.js/issues/84716">#84716</a>)</li>
<li>feat: <code>experimental.middlewareClientMaxBodySize</code> body
cloning limit (<a
href="https://redirect.github.com/vercel/next.js/issues/84722">#84722</a>)</li>
<li>fix: missing next/link types with typedRoutes (<a
href="https://redirect.github.com/vercel/next.js/issues/84779">#84779</a>)</li>
</ul>
<h3>Misc Changes</h3>
<ul>
<li>docs: early October improvements and fixes (<a
href="https://redirect.github.com/vercel/next.js/issues/84334">#84334</a>)</li>
</ul>
<h3>Credits</h3>
<p>Huge thanks to <a
href="https://github.com/devjiwonchoi"><code>@​devjiwonchoi</code></a>,
<a href="https://github.com/ztanner"><code>@​ztanner</code></a>, and <a
href="https://github.com/icyJoseph"><code>@​icyJoseph</code></a> for
helping!</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vercel/next.js/commit/55ef0e3ebc1d43e1a4a191341dc2a415e12124d4"><code>55ef0e3</code></a>
v15.5.6</li>
<li><a
href="https://github.com/vercel/next.js/commit/92bbbb1beca8738c783ea36ee5dd84d89cd638be"><code>92bbbb1</code></a>
Backport: don't define <code>process.cwd()</code> in node_modules (<a
href="https://redirect.github.com/vercel/next.js/issues/84957">#84957</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/f895b727626ad921d5068bcfada284f68c998bfa"><code>f895b72</code></a>
Fix url-imports test on 15-5 (<a
href="https://redirect.github.com/vercel/next.js/issues/84966">#84966</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/81f530db2652a96d4b88fabaf4dfaf30c2269695"><code>81f530d</code></a>
v15.5.5</li>
<li><a
href="https://github.com/vercel/next.js/commit/9abbc0e9eba67d635d4da5293273de123263101d"><code>9abbc0e</code></a>
[backport] fix: missing <code>next/link</code> types with
<code>typedRoutes</code> (<a
href="https://redirect.github.com/vercel/next.js/issues/82814">#82814</a>)
(<a
href="https://redirect.github.com/vercel/next.js/issues/84779">#84779</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/121e1b566f8bf632dd09bf06fbbdb5ff5a21a51c"><code>121e1b5</code></a>
[backport] docs: early October improvements and fixes (<a
href="https://redirect.github.com/vercel/next.js/issues/84334">#84334</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/1b276c98f98f2d06bb9be36634410851867b013f"><code>1b276c9</code></a>
[backport]: <code>experimental.middlewareClientMaxBodySize</code> (<a
href="https://redirect.github.com/vercel/next.js/issues/84722">#84722</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/2061f04132690956ac0722eeacdff8747d7c1c49"><code>2061f04</code></a>
[backport] fix: unstable_cache should perform blocking revalidation
during IS...</li>
<li><a
href="https://github.com/vercel/next.js/commit/ce3d9639d12eaa0fe05ba5cbc7a5d86daf3b3341"><code>ce3d963</code></a>
[backport] Add deprecation warning to Runtime config (<a
href="https://redirect.github.com/vercel/next.js/issues/84168">#84168</a>)
(<a
href="https://redirect.github.com/vercel/next.js/issues/84650">#84650</a>)</li>
<li><a
href="https://github.com/vercel/next.js/commit/ec69752d9e5b4174491cdded7b419ba7657db481"><code>ec69752</code></a>
[backport] Split code-frame into separate compiled package (<a
href="https://redirect.github.com/vercel/next.js/issues/84174">#84174</a>)
(<a
href="https://redirect.github.com/vercel/next.js/issues/84238">#84238</a>)</li>
<li>See full diff in <a
href="https://github.com/vercel/next.js/compare/v15.5.4...v15.5.6">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.4&new-version=15.5.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-11-01 11:18:01 +00:00
dependabot[bot] a899fc57a6 chore: bump @types/node from 20.19.19 to 20.19.24 in /offlinedocs (#20617)
Bumps
[@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)
from 20.19.19 to 20.19.24.
<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.19&new-version=20.19.24)](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-01 11:17:38 +00:00
Asher 77e2521fa0 feat: support workspace name in get workspace tool (#20474)
This lets the LLM skip the list workspace step in some cases.

Closes https://github.com/coder/internal/issues/1022
2025-10-31 15:10:36 -08:00
ケイラ c627a68e96 chore: migrate some tests from jest to vitest (#20568) 2025-10-31 15:15:30 -06:00
Mathias Fredriksson 7ae3fdc749 refactor: use task data model for notifications (#20590)
Updates coder/internal#973
Updates coder/internal#974
2025-10-31 15:53:27 +02:00
Spike Curtis 7b6e72438b chore: update quartz to 0.3.0 (#20604)
Upgrade coder/quartz dep to 0.3.0
2025-10-31 15:36:08 +04:00
Kacper Sawicki 8f78baddb1 feat(scaletest): switch notification trigger from creating a user to template deletion (#20512)
This PR refactors the notification scale test to use template admins and template deletion as the notification trigger. Additionally, I've added a configurable timeout for SMTP requests.

Previously, notifications were triggered by creating/deleting a user, and notifications were received by users with the owner role. However, because of how many notifications were generated by the runners, we had too many notifications to reliably test notification delivery.
2025-10-31 09:43:06 +01:00
Jake Howell 0f8f67ec6f chore: update paywall grammar mistake (#20602)
Resolved issue from #20331 where the article `an` was incorrectly used
before words not beginning with a vowel sound. Updated affected
instances to use the correct article `a`.

```diff
- You need an Premium license to use this feature.
+ You need a Premium license to use this feature.
```

This was already correct on the following pages.

*
[`ConnectionLogPageView.tsx`](https://github.com/coder/coder/blob/7182c53df7648cd7db8551629226c4a0a1cc8559/site/src/pages/ConnectionLogPage/ConnectionLogPageView.tsx#L130)
*
[`GroupsPageView.tsx`](https://github.com/coder/coder/blob/7182c53df7648cd7db8551629226c4a0a1cc8559/site/src/pages/GroupsPage/GroupsPageView.tsx#L49)
2025-10-31 15:34:51 +11:00
Jake Howell 9298e7e073 chore: remove @emotion/react from <404Page /> (#20530)
This PR removes the dependency on `@emotion/react` from the 404 page as
part of our ongoing effort to eliminate `@mui/` dependencies across the
codebase.

I’m slightly concerned that these Tailwind classes might not apply
correctly if Tailwind fails to load. If thats an issue, it might be
worth converting this page to raw CSS.
2025-10-31 14:55:14 +11:00
Dean Sheather 7182c53df7 chore: remove brazil fly.io proxy (#20601) 2025-10-31 02:40:56 +00:00
david-fraley 37222199c3 docs: update release calendar for 2.27.3 patch (#20597) 2025-10-31 06:25:01 +05:00
Ethan 9c47733e16 ci: allow more time for gen & fmt jobs to be acquired (#20577)
Closes https://github.com/coder/internal/issues/1081

The time taken for a runner to acquire a job counts towards the job-wide `timeout-minutes`. Recently we've been seeing outages in the runner infrastructure lead to a ~5-6m runner start time, causing fmt & gen jobs to be cancelled due to their 7 or 8 minute timeouts.

This PR extends the job-wide timeout on fmt & gen to 20 minutes, but adds the original 7 and 8 minute timeouts to the `make [fmt|gen]` portion of the job -- the part of the job we have the most control over, and that we want to be made aware of timeouts for.
2025-10-31 11:26:12 +11:00
Zach 139dab7cfe feat(cli): optionally store session token in OS keyring (#20256)
This change implements optional secure storage of the CLI token using the operating system
 keyring for Windows, with groundwork laid for macOS in a future change. Previously, the
 Coder CLI stored authentication tokens in plaintext configuration files, which posed a
 security risk because users' tokens are stored unencrypted and can be easily accessed by
 other processes or users with file system access.

The keyring is opt-in to preserve compatibility with applications (like the JetBrains
Toolbox plugin, VS code plugin, etc). Users can opt into keyring use with a new
`--use-keyring` flag.

The secure storage is platform dependent. Windows Credential Manager API is used on Windows.
The session token continues to be stored in plain text on macOS and Linux. macOS is omitted
for now while we figure out the best path forward for compatibility with apps like Coder Desktop.

https://www.notion.so/coderhq/CLI-Session-Token-in-OS-Keyring-293d579be592808b8b7fd235304e50d5

https://github.com/coder/coder/issues/19403
2025-10-30 17:41:08 -06:00
Asher d306a2d7e5 chore: log with %s on unexpected non-sdk err (#20570)
With `%w` it prints an address instead of the error, like `<op> <url>
0xc001329370` instead of `<op> <url>: some error`, honestly idk why you
even can log with `%w` it seems like it makes no sense to use `%w`
outside of `fmt.Errorf`.

This is to help debug https://github.com/coder/internal/issues/1010.
2025-10-30 10:23:52 -08:00
Rowan Smith 30d2fc8bfc fix: fix incorrect rendering of RBAC in Helm chart when workspacePerms=false (#20569) 2025-10-31 05:22:23 +11:00
Danielle Maywood d80b5fc8ed refactor!: remove TaskAppID from codersdk.WorkspaceBuild (#20583)
Remove the `TaskAppID` field from `codersdk.WorkspaceBuild`. Consumers can instead use the new `codersdk.Task` data model for this information.
2025-10-30 16:45:51 +00:00
Danielle Maywood 197b422a31 chore: add tzdata to dockerfile base (#20553)
When deploying Coder using the ghcr.io/coder/coder image, it is not
possible to set the "timezone" field in a preset with an embedded
provisioner. This is due to the container image not having the IANA time
zone database installed, which causes an issue when the terraform
provider attempts to validate the given timezone is valid.
2025-10-30 14:08:06 +00:00
Cian Johnston 38017010ce fix(coderd): disallow POSTing a workspace build on a deleted workspace (#20584)
- Adds a check on /api/v2/workspacebuilds to disallow creating a START or STOP build if the workspace is deleted. 
- DELETEs are still allowed.
2025-10-30 13:32:18 +00:00
Spike Curtis 984a834e81 docs: revert work in progress 10k scale doc (#20580)
Reverts in-progress 10k docs because people found it confusing.
2025-10-30 16:17:04 +04:00
Cian Johnston 2bcf08457b ci: revert workaround for get.helm.sh outage (#20552) (#20557)
Reverts the temporary workaround in #20552. 
Merge after get.helm.sh is once again operational.
2025-10-30 10:56:24 +00:00
Cian Johnston 73dedcc765 fix: delete related task when deleting workspace (#20567)
* Instead of prompting the user to start a deleted workspace (which is
silly), prompt them to create a new task instead.
* Adds a warning dialog when deleting a workspace
* Updates provisionerdserver to delete the related task if a workspace
is related to a task
2025-10-30 10:37:51 +00:00
Spike Curtis 94f6e83cfa docs: fix typo: worklods (#20578)
fixes typo.
2025-10-30 12:45:47 +04:00
Ethan bc0c4ebaa7 chore(dogfood): add back coder envbuilder template (#20576)
I've given the CI dev.coder user Admin on the template, and tested the template still builds a workspace.
2025-10-30 19:09:08 +11:00
Spike Curtis dc277618ee chore: refactor flags that target workspaces in scaletest (#20537)
For the https://github.com/coder/internal/issues/913 we are going to be targeting running workspaces. So this PR modularizes the CLI flags and logic that select those targets so we can reuse it.
2025-10-30 11:10:24 +04:00
Ethan b90c74a94d chore(scaletest): avoid polling workspace builds during workspace-updates tests (#20534)
This PR is just committing the changes I made while running the
`workspace-updates` load generator.

It ensures we're not polling the workspace build progress in the
background (while we also watch for workspace updates via the tailnet),
and also removes an unnecessary query to `/api/v2/workspace/{id}` after
each workspace is built.
2025-10-30 12:14:25 +11:00
Danny Kopping ff532d9bf3 chore: handle deprecated aibridge experimental routes (#20565)
In v2.28 we're [removing the aibridge
experiment](https://github.com/coder/coder/pull/20544).

We need to handle `/api/experimental/aibridge/*` until Beta (next
release).

Signed-off-by: Danny Kopping <danny@coder.com>
2025-10-29 19:11:34 -06:00
Steven Masley 54497f4f6b chore: add revocation endpoint to oauth well-known (#20561)
Was added to apps endpoints, but not the wider site ones. This is a site
wide oauth route
2025-10-29 16:44:53 -05:00
Danielle Maywood 9629d873fb fix(site): fix disappearing preset selector when switching task template (#20514)
Closes https://github.com/coder/coder/issues/20465

Ensure we set `selectedPresetId` to `undefined` when we change
`selectedTemplateId` to ensure we don't end up breaking the `<Select>`
component by giving it an invalid preset id.
2025-10-29 21:11:44 +00:00
Asher 643fe38b1e fix: use temp file on same device with mcp file edit (#20477)
Otherwise you can get errors like "invalid cross-device link".
2025-10-29 12:23:06 -08:00
Jaayden Halko c827a08c11 refactor: migrate deployment banner to Tailwind and radix (#20479)
before:
<img width="1667" height="48" alt="Screenshot 2025-10-25 at 18 02 45"
src="https://github.com/user-attachments/assets/1525a01e-5976-4d0e-8280-1b9ae8d91197"
/>

after:
<img width="1662" height="35" alt="Screenshot 2025-10-25 at 18 02 17"
src="https://github.com/user-attachments/assets/d0fd7b69-ee88-4986-a539-5917c17a8b85"
/>
2025-10-29 15:41:19 -04:00
Bartek Gatz 1b6556c2f6 fix: improve visual separation between prompt and task list (#20427) 2025-10-29 19:00:27 +00:00
Mathias Fredriksson 859e94d67a fix: deprecate codersdk.AITaskPromptParameterName and reduce usage (#20501)
Depends on coder/sqlc#1
Fixes coder/internal#979
Updates coder/internal#973
2025-10-29 18:59:12 +00:00
Cian Johnston 50749d131b ci: workaround for get.helm.sh outage (#20552)
<!--

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-10-29 17:33:03 +00:00
Dean Sheather 9986dc0c38 chore: remove brazil region from dogfood (#20548) 2025-10-29 13:03:14 -04:00
Dean Sheather 92b63871ca chore: remove dogfood envbuilder template deployment (#20546)
Already missing in state, verified with `terraform state list`
2025-10-29 13:03:00 -04:00
Mathias Fredriksson 303e9ef7de fix: switch to coder/sqlc fork (#20536)
Refs https://github.com/coder/sqlc/pull/1
Unblocks https://github.com/coder/coder/pull/20501

Upstream https://github.com/sqlc-dev/sqlc/pull/4159
2025-10-29 18:45:56 +02:00
Cian Johnston 1ebc217624 fix: update task link AppStatus using task_id (#20543)
Fixes https://github.com/coder/coder/issues/20515

Alternative to https://github.com/coder/coder/pull/20519

Adds `task_id` to `workspaces_expanded` view and updates the "View Task"
link in `AppStatuses` component.

NOTE: this contains a migration
2025-10-29 15:45:45 +00:00
Danielle Maywood 06dbadab11 fix(coderd): ensure lifecycle executor has sufficient task permissions (#20539)
We recently made a change to the `wsbuilder` to handle task related
logic. Our test coverage for the lifecycle executor didn't handle this
scenario and so we missed that it had insufficient permissions.

This PR adds `Update` and `Read` permissions for `Task`s in the
lifecycle executor, as well as an autostart/autostop test tailored to
task workspaces to verify the change.

---

Anthropic's Claude Sonnet 4.5 Thinking was involved in writing the tests
2025-10-29 15:44:35 +00:00
Cian Johnston 566146af72 fix(coderd): fix audit log resource link for tasks (#20545)
Existing task audit log links were incorrect. As audit log links are
generated on-the-fly, this does not require backfill.
2025-10-29 15:31:41 +00:00
Susana Ferreira 7e8fcb4b0f perf: optimize prebuilds membership reconciliation to check orgs not presets (#20493)
## Description

The membership reconciliation ensures the prebuilds system user is a
member of all organizations with prebuilds configured. To support
prebuilds quota management, each organization must have a prebuilds
group that the system user belongs to.

## Problem

Previously, membership reconciliation iterated over all presets to check
and update membership status. This meant database queries
`GetGroupByOrgAndName` and `InsertGroupMember` were executed for each
preset. Since presets are unique combinations of `(organization,
template, template version, preset)`, this resulted in several redundant
checks for the same organization.

In dogfood, `InsertGroupMember` was called thousands of times per day,
even though memberships were already configured ([internal Grafana
dashboard link](https://grafana.dev.coder.com/goto/46MZ1UgDg?orgId=1))

<img width="5382" height="1788" alt="Screenshot 2025-10-28 at 16 01 36"
src="https://github.com/user-attachments/assets/757b7253-106f-4f72-8586-8e2ede9f18db"
/>

## Solution

This PR introduces `GetOrganizationsWithPrebuildStatus`, a single query
that returns:
* All unique organizations with prebuilds configured
* Whether the prebuilds user is a member of each organization
* Whether the prebuilds group exists in each organization
* Whether the prebuilds user is in the prebuilds group

The membership reconciliation logic now:
* Fetches status for all organizations in one query
* Only performs inserts for organizations missing required memberships
or groups
* Safely handles concurrent operations via unique constraint violations
* This reduces database load from `O(presets)` to `O(organizations)` per
reconciliation loop, with a single read query when everything is
configured.

## Changes

* Add `GetOrganizationsWithPrebuildStatus` SQL query
* Update `membership.ReconcileAll` to use organization-based
reconciliation instead of preset-based
* Update tests to reflect new behavior

Related to internal thread:
https://codercom.slack.com/archives/C07GRNNRW03/p1760535570381369
2025-10-29 14:24:29 +00:00
Danny Kopping dd28eef5b4 chore: update dogfood template to use new aibridge endpoint (#20525)
Also updating Nix to 2.28.5 since the previous version 404s.

Closes https://github.com/coder/internal/issues/1105
2025-10-29 07:53:34 -06:00
Danny Kopping 2f886ce8d0 chore: update docs (#20521)
Updates AI Bridge docs to remove experiment details.
2025-10-29 07:43:33 -06:00
Danny Kopping dcfd6d6f73 chore: graduate aibridge cli out of experimental (#20524)
<!--

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-10-29 07:36:08 -06:00
Danny Kopping b20fd6f2c1 chore: graduate aibridge API out of experimental (#20523)
<!--

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-10-29 07:18:54 -06:00
Danny Kopping 2294c55bd9 chore: graduate aibridged* packages out of experimental (#20522)
<!--

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-10-29 07:00:24 -06:00
Susana Ferreira aad1b401c1 feat: add prebuilds reconciliation duration metric (#20535)
## Description

Adds `coderd_prebuilds_reconciliation_duration_seconds` histogram metric
to track the duration of each prebuilds reconciliation cycle.

This metric helps operators monitor reconciliation performance and
identify potential bottlenecks.

## Changes

- Added `ReconcileStats` struct to capture reconciliation cycle
statistics
- Updated `ReconcileAll()` to return stats including elapsed time
- Added histogram metric
`coderd_prebuilds_reconciliation_duration_seconds`
2025-10-29 12:52:30 +00:00
Steven Masley a8294872a3 chore: use consistent function for statefile path (#20527)
We use `getStateFilePath` in 2 locations, and a manual `filepath.Join`
here. Just refactored to use the helper function
2025-10-29 07:44:09 -05:00
Danny Kopping 95a1ca898f chore: remove aibridge experiment (#20520)
Removes the experiment and all references to it
2025-10-29 06:18:38 -06:00
Susana Ferreira c3e3bb58f2 feat: delete pending canceled prebuilds (#20499)
## Description

PR https://github.com/coder/coder/pull/20387 introduced canceling
pending prebuild jobs from inactive template versions to avoid
provisioning obsolete workspaces. However, the associated prebuilds
remained in the database with "Canceled" status, visible in the UI.

This PR now orphan-deletes these canceled prebuilt workspaces. Since the
canceled jobs were never processed by a provisioner, no Terraform
resources were created, making orphan deletion safe.

Orphan deletion always creates a provisioner job, but behaves
differently based on provisioner availability:
- If no provisioner daemon is available, the job is immediately marked
as completed and the workspace is marked as deleted without any
provisioner processing
- If a provisioner daemon is available, it processes the delete job with
empty Terraform state (no actual resources to destroy)

The job cancellation and workspace deletion occur atomically in the same
transaction. We don't split this into two separate reconciliation runs
because there's no way to distinguish between system-canceled prebuilds
and user-canceled workspaces. If we deleted canceled workspaces in a
later run, we'd delete user-canceled workspaces that users may want to
keep for troubleshooting.

Note: This only applies to system-generated prebuilds from inactive
template versions.

## Changes

* Update `UpdatePrebuildProvisionerJobWithCancel` query to return job
ID, workspace ID, template ID, and template version preset ID
* Add `DeprovisionMode` enum to support orphan deletion in the provision
flow
* Update `ActionTypeCancelPending` handler to cancel jobs and
orphan-delete associated workspaces atomically
2025-10-29 10:37:28 +00:00
Atif Ali 0d765f56f7 chore: update terraform to 1.13.4 (#20532)
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Ethan Dickson <ethan@coder.com>
2025-10-29 07:34:41 +00:00
452 changed files with 17982 additions and 7663 deletions
+2
View File
@@ -27,5 +27,7 @@ ignorePatterns:
- pattern: "splunk.com"
- pattern: "stackoverflow.com/questions"
- pattern: "developer.hashicorp.com/terraform/language"
- pattern: "platform.openai.com/docs/api-reference"
- pattern: "api.openai.com"
aliveStatusCodes:
- 200
+1 -1
View File
@@ -4,7 +4,7 @@ description: |
inputs:
version:
description: "The Go version to use."
default: "1.24.6"
default: "1.24.10"
use-preinstalled-go:
description: "Whether to use preinstalled Go."
default: "false"
+10 -3
View File
@@ -5,6 +5,13 @@ runs:
using: "composite"
steps:
- name: Setup sqlc
uses: sqlc-dev/setup-sqlc@c0209b9199cd1cce6a14fc27cabcec491b651761 # v4.0.0
with:
sqlc-version: "1.27.0"
# uses: sqlc-dev/setup-sqlc@c0209b9199cd1cce6a14fc27cabcec491b651761 # v4.0.0
# with:
# sqlc-version: "1.30.0"
# Switched to coder/sqlc fork to fix ambiguous column bug, see:
# - https://github.com/coder/sqlc/pull/1
# - https://github.com/sqlc-dev/sqlc/pull/4159
shell: bash
run: |
CGO_ENABLED=1 go install github.com/coder/sqlc/cmd/sqlc@aab4e865a51df0c43e1839f81a9d349b41d14f05
+1 -1
View File
@@ -7,5 +7,5 @@ runs:
- name: Install Terraform
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
with:
terraform_version: 1.13.0
terraform_version: 1.13.4
terraform_wrapper: false
@@ -1,34 +0,0 @@
app = "sao-paulo-coder"
primary_region = "gru"
[experimental]
entrypoint = ["/bin/sh", "-c", "CODER_DERP_SERVER_RELAY_URL=\"http://[${FLY_PRIVATE_IP}]:3000\" /opt/coder wsproxy server"]
auto_rollback = true
[build]
image = "ghcr.io/coder/coder-preview:main"
[env]
CODER_ACCESS_URL = "https://sao-paulo.fly.dev.coder.com"
CODER_HTTP_ADDRESS = "0.0.0.0:3000"
CODER_PRIMARY_ACCESS_URL = "https://dev.coder.com"
CODER_WILDCARD_ACCESS_URL = "*--apps.sao-paulo.fly.dev.coder.com"
CODER_VERBOSE = "true"
[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
# Ref: https://fly.io/docs/reference/configuration/#http_service-concurrency
[http_service.concurrency]
type = "requests"
soft_limit = 50
hard_limit = 100
[[vm]]
cpu_kind = "shared"
cpus = 2
memory_mb = 512
+31 -21
View File
@@ -35,7 +35,7 @@ jobs:
tailnet-integration: ${{ steps.filter.outputs.tailnet-integration }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -157,7 +157,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -191,7 +191,7 @@ jobs:
# Check for any typos
- name: Check for typos
uses: crate-ci/typos@80c8a4945eec0f6d464eaf9e65ed98ef085283d1 # v1.38.1
uses: crate-ci/typos@626c4bedb751ce0b7f03262ca97ddda9a076ae1c # v1.39.2
with:
config: .github/workflows/typos.toml
@@ -230,12 +230,12 @@ jobs:
shell: bash
gen:
timeout-minutes: 8
timeout-minutes: 20
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
if: ${{ !cancelled() }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -271,6 +271,7 @@ jobs:
popd
- name: make gen
timeout-minutes: 8
run: |
# Remove golden files to detect discrepancy in generated files.
make clean/golden-files
@@ -288,10 +289,10 @@ jobs:
needs: changes
if: needs.changes.outputs.offlinedocs-only == 'false' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main'
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
timeout-minutes: 7
timeout-minutes: 20
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -315,6 +316,7 @@ jobs:
run: go install mvdan.cc/sh/v3/cmd/shfmt@v3.7.0
- name: make fmt
timeout-minutes: 7
run: |
PATH="${PATH}:$(go env GOPATH)/bin" \
make --output-sync -j -B fmt
@@ -341,7 +343,7 @@ jobs:
- windows-2022
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -530,7 +532,7 @@ jobs:
timeout-minutes: 25
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -579,7 +581,7 @@ jobs:
timeout-minutes: 25
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -639,7 +641,7 @@ jobs:
timeout-minutes: 20
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -666,7 +668,7 @@ jobs:
timeout-minutes: 20
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -699,7 +701,7 @@ jobs:
name: ${{ matrix.variant.name }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -754,6 +756,14 @@ jobs:
path: ./site/test-results/**/*.webm
retention-days: 7
- name: Upload debug log
if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' && !github.event.pull_request.head.repo.fork
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: coderd-debug-logs${{ matrix.variant.premium && '-premium' || '' }}
path: ./site/e2e/test-results/debug.log
retention-days: 7
- name: Upload pprof dumps
if: always() && github.actor != 'dependabot[bot]' && runner.os == 'Linux' && !github.event.pull_request.head.repo.fork
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
@@ -771,7 +781,7 @@ jobs:
if: needs.changes.outputs.site == 'true' || needs.changes.outputs.ci == 'true'
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -792,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@bc2d84ad2b60813a67d995c5582d696104a19383 # v13.3.2
uses: chromaui/action@ac86f2ff0a458ffbce7b40698abd44c0fa34d4b6 # v13.3.3
env:
NODE_OPTIONS: "--max_old_space_size=4096"
STORYBOOK: true
@@ -824,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@bc2d84ad2b60813a67d995c5582d696104a19383 # v13.3.2
uses: chromaui/action@ac86f2ff0a458ffbce7b40698abd44c0fa34d4b6 # v13.3.3
env:
NODE_OPTIONS: "--max_old_space_size=4096"
STORYBOOK: true
@@ -852,7 +862,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -923,7 +933,7 @@ jobs:
if: always()
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -1043,7 +1053,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -1098,7 +1108,7 @@ jobs:
IMAGE: ghcr.io/coder/coder-preview:${{ steps.build-docker.outputs.tag }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -1495,7 +1505,7 @@ jobs:
if: needs.changes.outputs.db == 'true' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main'
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+4 -6
View File
@@ -36,7 +36,7 @@ jobs:
verdict: ${{ steps.check.outputs.verdict }} # DEPLOY or NOOP
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -65,7 +65,7 @@ jobs:
packages: write # to retag image as dogfood
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -92,7 +92,7 @@ jobs:
uses: google-github-actions/setup-gcloud@aa5489c8933f4cc7a4f7d45035b3b1440c9c10db # v3.0.1
- name: Set up Flux CLI
uses: fluxcd/flux2/action@4a15fa6a023259353ef750acf1c98fe88407d4d0 # v2.7.2
uses: fluxcd/flux2/action@b6e76ca2534f76dcb8dd94fb057cdfa923c3b641 # v2.7.3
with:
# Keep this and the github action up to date with the version of flux installed in dogfood cluster
version: "2.7.0"
@@ -146,7 +146,7 @@ jobs:
needs: deploy
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -163,12 +163,10 @@ jobs:
run: |
flyctl deploy --image "$IMAGE" --app paris-coder --config ./.github/fly-wsproxies/paris-coder.toml --env "CODER_PROXY_SESSION_TOKEN=$TOKEN_PARIS" --yes
flyctl deploy --image "$IMAGE" --app sydney-coder --config ./.github/fly-wsproxies/sydney-coder.toml --env "CODER_PROXY_SESSION_TOKEN=$TOKEN_SYDNEY" --yes
flyctl deploy --image "$IMAGE" --app sao-paulo-coder --config ./.github/fly-wsproxies/sao-paulo-coder.toml --env "CODER_PROXY_SESSION_TOKEN=$TOKEN_SAO_PAULO" --yes
flyctl deploy --image "$IMAGE" --app jnb-coder --config ./.github/fly-wsproxies/jnb-coder.toml --env "CODER_PROXY_SESSION_TOKEN=$TOKEN_JNB" --yes
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
IMAGE: ${{ inputs.image }}
TOKEN_PARIS: ${{ secrets.FLY_PARIS_CODER_PROXY_SESSION_TOKEN }}
TOKEN_SYDNEY: ${{ secrets.FLY_SYDNEY_CODER_PROXY_SESSION_TOKEN }}
TOKEN_SAO_PAULO: ${{ secrets.FLY_SAO_PAULO_CODER_PROXY_SESSION_TOKEN }}
TOKEN_JNB: ${{ secrets.FLY_JNB_CODER_PROXY_SESSION_TOKEN }}
+1 -1
View File
@@ -38,7 +38,7 @@ jobs:
if: github.repository_owner == 'coder'
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
- name: Setup Node
uses: ./.github/actions/setup-node
- uses: tj-actions/changed-files@dbf178ceecb9304128c8e0648591d71208c6e2c9 # v45.0.7
- uses: tj-actions/changed-files@70069877f29101175ed2b055d210fe8b1d54d7d7 # v45.0.7
id: changed-files
with:
files: |
+3 -3
View File
@@ -26,7 +26,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-4' || 'ubuntu-latest' }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -40,7 +40,7 @@ jobs:
with:
# Pinning to 2.28 here, as Nix gets a "error: [json.exception.type_error.302] type must be array, but is string"
# on version 2.29 and above.
nix_version: "2.28.4"
nix_version: "2.28.5"
- uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6.1.3
with:
@@ -125,7 +125,7 @@ jobs:
id-token: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+1 -1
View File
@@ -27,7 +27,7 @@ jobs:
- windows-2022
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
packages: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+5 -5
View File
@@ -39,7 +39,7 @@ jobs:
PR_OPEN: ${{ steps.check_pr.outputs.pr_open }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -76,7 +76,7 @@ jobs:
runs-on: "ubuntu-latest"
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -184,7 +184,7 @@ jobs:
pull-requests: write # needed for commenting on PRs
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -228,7 +228,7 @@ jobs:
CODER_IMAGE_TAG: ${{ needs.get_info.outputs.CODER_IMAGE_TAG }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -288,7 +288,7 @@ jobs:
PR_HOSTNAME: "pr${{ needs.get_info.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+1 -1
View File
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+5 -5
View File
@@ -164,7 +164,7 @@ jobs:
version: ${{ steps.version.outputs.version }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -785,7 +785,7 @@ jobs:
- name: Send repository-dispatch event
if: ${{ !inputs.dry_run }}
uses: peter-evans/repository-dispatch@5fc4efd1a4797ddb68ffd0714a238564e4cc0e6f # v4.0.0
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
with:
token: ${{ secrets.CDRCI_GITHUB_TOKEN }}
repository: coder/packages
@@ -802,7 +802,7 @@ jobs:
# TODO: skip this if it's not a new release (i.e. a backport). This is
# fine right now because it just makes a PR that we can close.
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -878,7 +878,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -971,7 +971,7 @@ jobs:
if: ${{ !inputs.dry_run }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+2 -2
View File
@@ -20,7 +20,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -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@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v3.29.5
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
with:
sarif_file: results.sarif
+5 -5
View File
@@ -27,7 +27,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -40,7 +40,7 @@ jobs:
uses: ./.github/actions/setup-go
- name: Initialize CodeQL
uses: github/codeql-action/init@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v3.29.5
uses: github/codeql-action/init@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
with:
languages: go, javascript
@@ -50,7 +50,7 @@ jobs:
rm Makefile
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v3.29.5
uses: github/codeql-action/analyze@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
- name: Send Slack notification on failure
if: ${{ failure() }}
@@ -69,7 +69,7 @@ jobs:
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -154,7 +154,7 @@ jobs:
severity: "CRITICAL,HIGH"
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v3.29.5
uses: github/codeql-action/upload-sarif@014f16e7ab1402f30e7c3329d33797e7948572db # v3.29.5
with:
sarif_file: trivy-results.sarif
category: "Trivy"
+5 -5
View File
@@ -18,7 +18,7 @@ jobs:
pull-requests: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -96,7 +96,7 @@ jobs:
contents: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
@@ -120,12 +120,12 @@ jobs:
actions: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
- name: Delete PR Cleanup workflow runs
uses: Mattraks/delete-workflow-runs@ab482449ba468316e9a8801e092d0405715c5e6d # v2.1.0
uses: Mattraks/delete-workflow-runs@5bf9a1dac5c4d041c029f0a8370ddf0c5cb5aeb7 # v2.1.0
with:
token: ${{ github.token }}
repository: ${{ github.repository }}
@@ -134,7 +134,7 @@ jobs:
delete_workflow_pattern: pr-cleanup.yaml
- name: Delete PR Deploy workflow skipped runs
uses: Mattraks/delete-workflow-runs@ab482449ba468316e9a8801e092d0405715c5e6d # v2.1.0
uses: Mattraks/delete-workflow-runs@5bf9a1dac5c4d041c029f0a8370ddf0c5cb5aeb7 # v2.1.0
with:
token: ${{ github.token }}
repository: ${{ github.repository }}
+49 -76
View File
@@ -17,8 +17,8 @@ on:
type: string
template_preset:
description: "Template preset to use"
required: true
default: "none"
required: false
default: ""
type: string
prefix:
description: "Prefix for workspace name"
@@ -67,7 +67,7 @@ jobs:
GITHUB_EVENT_USER_LOGIN: ${{ github.event.sender.login }}
INPUTS_ISSUE_URL: ${{ inputs.issue_url }}
INPUTS_TEMPLATE_NAME: ${{ inputs.template_name || 'coder' }}
INPUTS_TEMPLATE_PRESET: ${{ inputs.template_preset || 'none'}}
INPUTS_TEMPLATE_PRESET: ${{ inputs.template_preset || ''}}
INPUTS_PREFIX: ${{ inputs.prefix || 'traiage' }}
GH_TOKEN: ${{ github.token }}
run: |
@@ -124,7 +124,7 @@ jobs:
exit 1
fi
- name: Extract context key from issue
- name: Extract context key and description from issue
id: extract-context
env:
ISSUE_URL: ${{ steps.determine-inputs.outputs.issue_url }}
@@ -132,86 +132,59 @@ jobs:
run: |
issue_number="$(gh issue view "${ISSUE_URL}" --json number --jq '.number')"
context_key="gh-${issue_number}"
echo "context_key=${context_key}" >> "${GITHUB_OUTPUT}"
echo "CONTEXT_KEY=${context_key}" >> "${GITHUB_ENV}"
- name: Download and install Coder binary
shell: bash
env:
CODER_URL: ${{ secrets.TRAIAGE_CODER_URL }}
run: |
if [ "${{ runner.arch }}" == "ARM64" ]; then
ARCH="arm64"
else
ARCH="amd64"
fi
mkdir -p "${HOME}/.local/bin"
curl -fsSL --compressed "$CODER_URL/bin/coder-linux-${ARCH}" -o "${HOME}/.local/bin/coder"
chmod +x "${HOME}/.local/bin/coder"
export PATH="$HOME/.local/bin:$PATH"
coder version
coder whoami
echo "$HOME/.local/bin" >> "${GITHUB_PATH}"
TASK_PROMPT=$(cat <<EOF
Fix ${ISSUE_URL}
- name: Get Coder username from GitHub actor
id: get-coder-username
env:
CODER_SESSION_TOKEN: ${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }}
GH_TOKEN: ${{ github.token }}
GITHUB_USER_ID: ${{ steps.determine-inputs.outputs.github_user_id }}
run: |
user_json=$(
coder users list --github-user-id="${GITHUB_USER_ID}" --output=json
1. Use the gh CLI to read the issue description and comments.
2. Think carefully and try to understand the root cause. If the issue is unclear or not well defined, ask me to clarify and provide more information.
3. Write a proposed implementation plan to PLAN.md for me to review before starting implementation. Your plan should use TDD and only make the minimal changes necessary to fix the root cause.
4. When I approve your plan, start working on it. If you encounter issues with the plan, ask me for clarification and update the plan as required.
5. When you have finished implementation according to the plan, commit and push your changes, and create a PR using the gh CLI for me to review.
EOF
)
coder_username=$(jq -r 'first | .username' <<< "$user_json")
[[ -z "${coder_username}" || "${coder_username}" == "null" ]] && echo "No Coder user with GitHub user ID ${GITHUB_USER_ID} found" && exit 1
echo "coder_username=${coder_username}" >> "${GITHUB_OUTPUT}"
echo "context_key=${context_key}" >> "${GITHUB_OUTPUT}"
{
echo "TASK_PROMPT<<EOF"
echo "${TASK_PROMPT}"
echo "EOF"
} >> "${GITHUB_OUTPUT}"
- name: Checkout repository
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
fetch-depth: 1
path: ./.github/actions/create-task-action
persist-credentials: false
fetch-depth: 0
ref: main
repository: coder/create-task-action
# TODO(Cian): this is a good use-case for 'recipes'
- name: Create Coder task
id: create-task
- name: Create Coder Task
id: create_task
uses: ./.github/actions/create-task-action
with:
coder-url: ${{ secrets.TRAIAGE_CODER_URL }}
coder-token: ${{ secrets.TRAIAGE_CODER_SESSION_TOKEN }}
coder-organization: "default"
coder-template-name: coder
coder-template-preset: ${{ steps.determine-inputs.outputs.template_preset }}
coder-task-name-prefix: gh-coder
coder-task-prompt: ${{ steps.extract-context.outputs.task_prompt }}
github-user-id: ${{ steps.determine-inputs.outputs.github_user_id }}
github-token: ${{ github.token }}
github-issue-url: ${{ steps.determine-inputs.outputs.issue_url }}
comment-on-issue: ${{ startsWith(steps.determine-inputs.outputs.issue_url, format('{0}/{1}', github.server_url, github.repository)) }}
- name: Write outputs
env:
CODER_USERNAME: ${{ steps.get-coder-username.outputs.coder_username }}
CONTEXT_KEY: ${{ steps.extract-context.outputs.context_key }}
GH_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
ISSUE_URL: ${{ steps.determine-inputs.outputs.issue_url }}
PREFIX: ${{ steps.determine-inputs.outputs.prefix }}
RUN_ID: ${{ github.run_id }}
TEMPLATE_NAME: ${{ steps.determine-inputs.outputs.template_name }}
TEMPLATE_PARAMETERS: ${{ secrets.TRAIAGE_TEMPLATE_PARAMETERS }}
TEMPLATE_PRESET: ${{ steps.determine-inputs.outputs.template_preset }}
TASK_CREATED: ${{ steps.create_task.outputs.task-created }}
TASK_NAME: ${{ steps.create_task.outputs.task-name }}
TASK_URL: ${{ steps.create_task.outputs.task-url }}
run: |
# Fetch issue description using `gh` CLI
#shellcheck disable=SC2016 # The template string should not be subject to shell expansion
issue_description=$(gh issue view "${ISSUE_URL}" \
--json 'title,body,comments' \
--template '{{printf "%s\n\n%s\n\nComments:\n" .title .body}}{{range $k, $v := .comments}} - {{index $v.author "login"}}: {{printf "%s\n" $v.body}}{{end}}')
# Write a prompt to PROMPT_FILE
PROMPT=$(cat <<EOF
Fix ${ISSUE_URL}
Analyze the below GitHub issue description, understand the root cause, and make appropriate changes to resolve the issue.
---
${issue_description}
EOF
)
export PROMPT
export TASK_NAME="${PREFIX}-${CONTEXT_KEY}-${RUN_ID}"
echo "Creating task: $TASK_NAME"
./scripts/traiage.sh create
if [[ "${ISSUE_URL}" == "https://github.com/${GITHUB_REPOSITORY}"* ]]; then
gh issue comment "${ISSUE_URL}" --body "Task created: https://dev.coder.com/tasks/${CODER_USERNAME}/${TASK_NAME}" --create-if-none --edit-last
else
echo "Skipping comment on other repo."
fi
echo "TASK_NAME=${CODER_USERNAME}/${TASK_NAME}" >> "${GITHUB_OUTPUT}"
echo "TASK_NAME=${CODER_USERNAME}/${TASK_NAME}" >> "${GITHUB_ENV}"
{
echo "**Task created:** ${TASK_CREATED}"
echo "**Task name:** ${TASK_NAME}"
echo "**Task URL**: ${TASK_URL}"
} >> "${GITHUB_STEP_SUMMARY}"
+1 -1
View File
@@ -21,7 +21,7 @@ jobs:
pull-requests: write # required to post PR review comments by the action
steps:
- name: Harden Runner
uses: step-security/harden-runner@f4a75cfd619ee5ce8d5b864b0d183aff3c69b55a # v2.13.1
uses: step-security/harden-runner@95d9a5deda9de15063e7595e9719c11c38c90ae2 # v2.13.2
with:
egress-policy: audit
+3
View File
@@ -91,3 +91,6 @@ __debug_bin*
**/.claude/settings.local.json
/.env
# Ignore plans written by AI agents.
PLAN.md
+8 -8
View File
@@ -636,8 +636,8 @@ TAILNETTEST_MOCKS := \
tailnet/tailnettest/subscriptionmock.go
AIBRIDGED_MOCKS := \
enterprise/x/aibridged/aibridgedmock/clientmock.go \
enterprise/x/aibridged/aibridgedmock/poolmock.go
enterprise/aibridged/aibridgedmock/clientmock.go \
enterprise/aibridged/aibridgedmock/poolmock.go
GEN_FILES := \
tailnet/proto/tailnet.pb.go \
@@ -645,7 +645,7 @@ GEN_FILES := \
provisionersdk/proto/provisioner.pb.go \
provisionerd/proto/provisionerd.pb.go \
vpn/vpn.pb.go \
enterprise/x/aibridged/proto/aibridged.pb.go \
enterprise/aibridged/proto/aibridged.pb.go \
$(DB_GEN_FILES) \
$(SITE_GEN_FILES) \
coderd/rbac/object_gen.go \
@@ -697,7 +697,7 @@ gen/mark-fresh:
provisionersdk/proto/provisioner.pb.go \
provisionerd/proto/provisionerd.pb.go \
vpn/vpn.pb.go \
enterprise/x/aibridged/proto/aibridged.pb.go \
enterprise/aibridged/proto/aibridged.pb.go \
coderd/database/dump.sql \
$(DB_GEN_FILES) \
site/src/api/typesGenerated.ts \
@@ -768,8 +768,8 @@ codersdk/workspacesdk/agentconnmock/agentconnmock.go: codersdk/workspacesdk/agen
go generate ./codersdk/workspacesdk/agentconnmock/
touch "$@"
$(AIBRIDGED_MOCKS): enterprise/x/aibridged/client.go enterprise/x/aibridged/pool.go
go generate ./enterprise/x/aibridged/aibridgedmock/
$(AIBRIDGED_MOCKS): enterprise/aibridged/client.go enterprise/aibridged/pool.go
go generate ./enterprise/aibridged/aibridgedmock/
touch "$@"
agent/agentcontainers/dcspec/dcspec_gen.go: \
@@ -822,13 +822,13 @@ vpn/vpn.pb.go: vpn/vpn.proto
--go_opt=paths=source_relative \
./vpn/vpn.proto
enterprise/x/aibridged/proto/aibridged.pb.go: enterprise/x/aibridged/proto/aibridged.proto
enterprise/aibridged/proto/aibridged.pb.go: enterprise/aibridged/proto/aibridged.proto
protoc \
--go_out=. \
--go_opt=paths=source_relative \
--go-drpc_out=. \
--go-drpc_opt=paths=source_relative \
./enterprise/x/aibridged/proto/aibridged.proto
./enterprise/aibridged/proto/aibridged.proto
site/src/api/typesGenerated.ts: site/node_modules/.installed $(wildcard scripts/apitypings/*) $(shell find ./codersdk $(FIND_EXCLUSIONS) -type f -name '*.go')
# -C sets the directory for the go run command
+3 -1
View File
@@ -250,7 +250,9 @@ func (a *agent) editFile(ctx context.Context, path string, edits []workspacesdk.
transforms[i] = replace.String(edit.Search, edit.Replace)
}
tmpfile, err := afero.TempFile(a.filesystem, "", filepath.Base(path))
// Create an adjacent file to ensure it will be on the same device and can be
// moved atomically.
tmpfile, err := afero.TempFile(a.filesystem, filepath.Dir(path), filepath.Base(path))
if err != nil {
return http.StatusInternalServerError, err
}
+1 -1
View File
@@ -58,7 +58,7 @@ func (g *Graph[EdgeType, VertexType]) AddEdge(from, to VertexType, edge EdgeType
toID := g.getOrCreateVertexID(to)
if g.canReach(to, from) {
return xerrors.Errorf("adding edge (%v -> %v) would create a cycle", from, to)
return xerrors.Errorf("adding edge (%v -> %v): %w", from, to, ErrCycleDetected)
}
g.gonumGraph.SetEdge(simple.Edge{F: simple.Node(fromID), T: simple.Node(toID)})
+3 -5
View File
@@ -148,8 +148,7 @@ func TestGraph(t *testing.T) {
graph := &testGraph{}
unit1 := &testGraphVertex{Name: "unit1"}
err := graph.AddEdge(unit1, unit1, testEdgeCompleted)
require.Error(t, err)
require.ErrorContains(t, err, fmt.Sprintf("adding edge (%v -> %v) would create a cycle", unit1, unit1))
require.ErrorIs(t, err, unit.ErrCycleDetected)
return graph
},
@@ -160,8 +159,7 @@ func TestGraph(t *testing.T) {
err := graph.AddEdge(unit1, unit2, testEdgeCompleted)
require.NoError(t, err)
err = graph.AddEdge(unit2, unit1, testEdgeStarted)
require.Error(t, err)
require.ErrorContains(t, err, fmt.Sprintf("adding edge (%v -> %v) would create a cycle", unit2, unit1))
require.ErrorIs(t, err, unit.ErrCycleDetected)
return graph
},
@@ -341,7 +339,7 @@ func TestGraphThreadSafety(t *testing.T) {
// Verify all attempts correctly returned cycle error
for i, err := range cycleErrors {
require.Error(t, err, "goroutine %d should have detected cycle", i)
require.Contains(t, err.Error(), "would create a cycle")
require.ErrorIs(t, err, unit.ErrCycleDetected)
}
// Verify graph remains valid (original chain intact)
+255
View File
@@ -0,0 +1,255 @@
package unit
import (
"errors"
"sync"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/coderd/util/slice"
)
var (
ErrUnitNotFound = xerrors.New("unit not found")
ErrUnitAlreadyRegistered = xerrors.New("unit already registered")
ErrCannotUpdateOtherUnit = xerrors.New("cannot update other unit's status")
ErrDependenciesNotSatisfied = xerrors.New("unit dependencies not satisfied")
ErrSameStatusAlreadySet = xerrors.New("same status already set")
ErrCycleDetected = xerrors.New("cycle detected")
ErrFailedToAddDependency = xerrors.New("failed to add dependency")
)
// Status represents the status of a unit.
type Status string
// Status constants for dependency tracking.
const (
StatusNotRegistered Status = ""
StatusPending Status = "pending"
StatusStarted Status = "started"
StatusComplete Status = "completed"
)
// ID provides a type narrowed representation of the unique identifier of a unit.
type ID string
// Unit represents a point-in-time snapshot of a vertex in the dependency graph.
// Units may depend on other units, or be depended on by other units. The unit struct
// is not aware of updates made to the dependency graph after it is initialized and should
// not be cached.
type Unit struct {
id ID
status Status
// ready is true if all dependencies are satisfied.
// It does not have an accessor method on Unit, because a unit cannot know whether it is ready.
// Only the Manager can calculate whether a unit is ready based on knowledge of the dependency graph.
// To discourage use of an outdated readiness value, only the Manager should set and return this field.
ready bool
}
func (u Unit) ID() ID {
return u.id
}
func (u Unit) Status() Status {
return u.status
}
// Dependency represents a dependency relationship between units.
type Dependency struct {
Unit ID
DependsOn ID
RequiredStatus Status
CurrentStatus Status
IsSatisfied bool
}
// Manager provides reactive dependency tracking over a Graph.
// It manages Unit registration, dependency relationships, and status updates
// with automatic recalculation of readiness when dependencies are satisfied.
type Manager struct {
mu sync.RWMutex
// The underlying graph that stores dependency relationships
graph *Graph[Status, ID]
// Store vertex instances for each unit to ensure consistent references
units map[ID]Unit
}
// NewManager creates a new Manager instance.
func NewManager() *Manager {
return &Manager{
graph: &Graph[Status, ID]{},
units: make(map[ID]Unit),
}
}
// Register adds a unit to the manager if it is not already registered.
// If a Unit is already registered (per the ID field), it is not updated.
func (m *Manager) Register(id ID) error {
m.mu.Lock()
defer m.mu.Unlock()
if m.registered(id) {
return xerrors.Errorf("registering unit %q: %w", id, ErrUnitAlreadyRegistered)
}
m.units[id] = Unit{
id: id,
status: StatusPending,
ready: true,
}
return nil
}
// registered checks if a unit is registered in the manager.
func (m *Manager) registered(id ID) bool {
return m.units[id].status != StatusNotRegistered
}
// Unit fetches a unit from the manager. If the unit does not exist,
// it returns the Unit zero-value as a placeholder unit, because
// units may depend on other units that have not yet been created.
func (m *Manager) Unit(id ID) Unit {
m.mu.RLock()
defer m.mu.RUnlock()
return m.units[id]
}
func (m *Manager) IsReady(id ID) bool {
m.mu.RLock()
defer m.mu.RUnlock()
if !m.registered(id) {
return false
}
return m.units[id].ready
}
// AddDependency adds a dependency relationship between units.
// The unit depends on the dependsOn unit reaching the requiredStatus.
func (m *Manager) AddDependency(unit ID, dependsOn ID, requiredStatus Status) error {
m.mu.Lock()
defer m.mu.Unlock()
if !m.registered(unit) {
return xerrors.Errorf("checking registration for unit %q: %w", unit, ErrUnitNotFound)
}
// Add the dependency edge to the graph
// The edge goes from unit to dependsOn, representing the dependency
err := m.graph.AddEdge(unit, dependsOn, requiredStatus)
if err != nil {
return xerrors.Errorf("adding edge for unit %q: %w", unit, errors.Join(ErrFailedToAddDependency, err))
}
// Recalculate readiness for the unit since it now has a new dependency
m.recalculateReadinessUnsafe(unit)
return nil
}
// UpdateStatus updates a unit's status and recalculates readiness for affected dependents.
func (m *Manager) UpdateStatus(unit ID, newStatus Status) error {
m.mu.Lock()
defer m.mu.Unlock()
if !m.registered(unit) {
return xerrors.Errorf("checking registration for unit %q: %w", unit, ErrUnitNotFound)
}
u := m.units[unit]
if u.status == newStatus {
return xerrors.Errorf("checking status for unit %q: %w", unit, ErrSameStatusAlreadySet)
}
u.status = newStatus
m.units[unit] = u
// Get all units that depend on this one (reverse adjacent vertices)
dependents := m.graph.GetReverseAdjacentVertices(unit)
// Recalculate readiness for all dependents
for _, dependent := range dependents {
m.recalculateReadinessUnsafe(dependent.From)
}
return nil
}
// recalculateReadinessUnsafe recalculates the readiness state for a unit.
// This method assumes the caller holds the write lock.
func (m *Manager) recalculateReadinessUnsafe(unit ID) {
u := m.units[unit]
dependencies := m.graph.GetForwardAdjacentVertices(unit)
allSatisfied := true
for _, dependency := range dependencies {
requiredStatus := dependency.Edge
dependsOnUnit := m.units[dependency.To]
if dependsOnUnit.status != requiredStatus {
allSatisfied = false
break
}
}
u.ready = allSatisfied
m.units[unit] = u
}
// GetGraph returns the underlying graph for visualization and debugging.
// This should be used carefully as it exposes the internal graph structure.
func (m *Manager) GetGraph() *Graph[Status, ID] {
return m.graph
}
// GetAllDependencies returns all dependencies for a unit, both satisfied and unsatisfied.
func (m *Manager) GetAllDependencies(unit ID) ([]Dependency, error) {
m.mu.RLock()
defer m.mu.RUnlock()
if !m.registered(unit) {
return nil, xerrors.Errorf("checking registration for unit %q: %w", unit, ErrUnitNotFound)
}
dependencies := m.graph.GetForwardAdjacentVertices(unit)
var allDependencies []Dependency
for _, dependency := range dependencies {
dependsOnUnit := m.units[dependency.To]
requiredStatus := dependency.Edge
allDependencies = append(allDependencies, Dependency{
Unit: unit,
DependsOn: dependsOnUnit.id,
RequiredStatus: requiredStatus,
CurrentStatus: dependsOnUnit.status,
IsSatisfied: dependsOnUnit.status == requiredStatus,
})
}
return allDependencies, nil
}
// GetUnmetDependencies returns a list of unsatisfied dependencies for a unit.
func (m *Manager) GetUnmetDependencies(unit ID) ([]Dependency, error) {
allDependencies, err := m.GetAllDependencies(unit)
if err != nil {
return nil, err
}
var unmetDependencies []Dependency = slice.Filter(allDependencies, func(dependency Dependency) bool {
return !dependency.IsSatisfied
})
return unmetDependencies, nil
}
// ExportDOT exports the dependency graph to DOT format for visualization.
func (m *Manager) ExportDOT(name string) (string, error) {
return m.graph.ToDOT(name)
}
+594
View File
@@ -0,0 +1,594 @@
package unit_test
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/agent/unit"
)
const (
unitA unit.ID = "serviceA"
unitB unit.ID = "serviceB"
unitC unit.ID = "serviceC"
unitD unit.ID = "serviceD"
)
func TestManager_Register(t *testing.T) {
t.Parallel()
t.Run("RegisterNewUnit", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given: a unit is registered
err := manager.Register(unitA)
require.NoError(t, err)
// Then: the unit should be ready (no dependencies)
u := manager.Unit(unitA)
assert.Equal(t, unitA, u.ID())
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitA))
})
t.Run("RegisterDuplicateUnit", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given: a unit is registered
err := manager.Register(unitA)
require.NoError(t, err)
// Newly registered units have StatusPending. We update the unit status to StatusStarted,
// so we can later assert that it is not overwritten back to StatusPending by the second
// register call
manager.UpdateStatus(unitA, unit.StatusStarted)
// When: the unit is registered again
err = manager.Register(unitA)
// Then: a descriptive error should be returned
require.ErrorIs(t, err, unit.ErrUnitAlreadyRegistered)
// Then: the unit status should not be overwritten
u := manager.Unit(unitA)
assert.Equal(t, unit.StatusStarted, u.Status())
assert.True(t, manager.IsReady(unitA))
})
t.Run("RegisterMultipleUnits", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given: multiple units are registered
unitIDs := []unit.ID{unitA, unitB, unitC}
for _, unit := range unitIDs {
err := manager.Register(unit)
require.NoError(t, err)
}
// Then: all units should be ready initially
for _, unitID := range unitIDs {
u := manager.Unit(unitID)
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitID))
}
})
}
func TestManager_AddDependency(t *testing.T) {
t.Parallel()
t.Run("AddDependencyBetweenRegisteredUnits", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given: units A and B are registered
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
// Given: Unit A depends on Unit B being unit.StatusStarted
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should not be ready (depends on B)
u := manager.Unit(unitA)
assert.Equal(t, unit.StatusPending, u.Status())
assert.False(t, manager.IsReady(unitA))
// Then: Unit B should still be ready (no dependencies)
u = manager.Unit(unitB)
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitB))
// When: Unit B is started
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should be ready, because its dependency is now in the desired state.
assert.True(t, manager.IsReady(unitA))
// When: Unit B is stopped
err = manager.UpdateStatus(unitB, unit.StatusPending)
require.NoError(t, err)
// Then: Unit A should no longer be ready, because its dependency is not in the desired state.
assert.False(t, manager.IsReady(unitA))
})
t.Run("AddDependencyByAnUnregisteredDependentUnit", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given Unit B is registered
err := manager.Register(unitB)
require.NoError(t, err)
// Given Unit A depends on Unit B being started
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
// Then: a descriptive error communicates that the dependency cannot be added
// because the dependent unit must be registered first.
require.ErrorIs(t, err, unit.ErrUnitNotFound)
})
t.Run("AddDependencyOnAnUnregisteredUnit", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given unit A is registered
err := manager.Register(unitA)
require.NoError(t, err)
// Given Unit B is not yet registered
// And Unit A depends on Unit B being started
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
u := manager.Unit(unitB)
assert.Equal(t, unit.StatusNotRegistered, u.Status())
// Then: Unit A should not be ready, because it depends on Unit B
assert.False(t, manager.IsReady(unitA))
// When: Unit B is registered
err = manager.Register(unitB)
require.NoError(t, err)
// Then: Unit A should still not be ready.
// Unit B is not registered, but it has not been started as required by the dependency.
assert.False(t, manager.IsReady(unitA))
// When: Unit B is started
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should be ready, because its dependency is now in the desired state.
assert.True(t, manager.IsReady(unitA))
})
t.Run("AddDependencyCreatesACyclicDependency", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Register units
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
err = manager.Register(unitC)
require.NoError(t, err)
err = manager.Register(unitD)
require.NoError(t, err)
// A depends on B
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
// B depends on C
err = manager.AddDependency(unitB, unitC, unit.StatusStarted)
require.NoError(t, err)
// C depends on D
err = manager.AddDependency(unitC, unitD, unit.StatusStarted)
require.NoError(t, err)
// Try to make D depend on A (creates indirect cycle)
err = manager.AddDependency(unitD, unitA, unit.StatusStarted)
require.ErrorIs(t, err, unit.ErrCycleDetected)
})
}
func TestManager_UpdateStatus(t *testing.T) {
t.Parallel()
t.Run("UpdateStatusTriggersReadinessRecalculation", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given units A and B are registered
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
// Given Unit A depends on Unit B being unit.StatusStarted
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should not be ready (depends on B)
u := manager.Unit(unitA)
assert.Equal(t, unit.StatusPending, u.Status())
assert.False(t, manager.IsReady(unitA))
// When: Unit B is started
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should be ready, because its dependency is now in the desired state.
u = manager.Unit(unitA)
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitA))
})
t.Run("UpdateStatusWithUnregisteredUnit", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given Unit A is not registered
// When: Unit A is updated to unit.StatusStarted
err := manager.UpdateStatus(unitA, unit.StatusStarted)
// Then: a descriptive error communicates that the unit must be registered first.
require.ErrorIs(t, err, unit.ErrUnitNotFound)
})
t.Run("LinearChainDependencies", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given units A, B, and C are registered
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
err = manager.Register(unitC)
require.NoError(t, err)
// Create chain: A depends on B being "started", B depends on C being "completed"
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
err = manager.AddDependency(unitB, unitC, unit.StatusComplete)
require.NoError(t, err)
// Then: only Unit C should be ready (no dependencies)
u := manager.Unit(unitC)
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitC))
u = manager.Unit(unitB)
assert.Equal(t, unit.StatusPending, u.Status())
assert.False(t, manager.IsReady(unitB))
u = manager.Unit(unitA)
assert.Equal(t, unit.StatusPending, u.Status())
assert.False(t, manager.IsReady(unitA))
// When: Unit C is completed
err = manager.UpdateStatus(unitC, unit.StatusComplete)
require.NoError(t, err)
// Then: Unit B should be ready, because its dependency is now in the desired state.
u = manager.Unit(unitB)
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitB))
u = manager.Unit(unitA)
assert.Equal(t, unit.StatusPending, u.Status())
assert.False(t, manager.IsReady(unitA))
u = manager.Unit(unitB)
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitB))
// When: Unit B is started
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should be ready, because its dependency is now in the desired state.
u = manager.Unit(unitA)
assert.Equal(t, unit.StatusPending, u.Status())
assert.True(t, manager.IsReady(unitA))
})
}
func TestManager_GetUnmetDependencies(t *testing.T) {
t.Parallel()
t.Run("GetUnmetDependenciesForUnitWithNoDependencies", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given: Unit A is registered
err := manager.Register(unitA)
require.NoError(t, err)
// Given: Unit A has no dependencies
// Then: Unit A should have no unmet dependencies
unmet, err := manager.GetUnmetDependencies(unitA)
require.NoError(t, err)
assert.Empty(t, unmet)
})
t.Run("GetUnmetDependenciesForUnitWithUnsatisfiedDependencies", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
// Given: Unit A depends on Unit B being unit.StatusStarted
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
unmet, err := manager.GetUnmetDependencies(unitA)
require.NoError(t, err)
require.Len(t, unmet, 1)
assert.Equal(t, unitA, unmet[0].Unit)
assert.Equal(t, unitB, unmet[0].DependsOn)
assert.Equal(t, unit.StatusStarted, unmet[0].RequiredStatus)
assert.False(t, unmet[0].IsSatisfied)
})
t.Run("GetUnmetDependenciesForUnitWithSatisfiedDependencies", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given: Unit A and Unit B are registered
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
// Given: Unit A depends on Unit B being unit.StatusStarted
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
// When: Unit B is started
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should have no unmet dependencies
unmet, err := manager.GetUnmetDependencies(unitA)
require.NoError(t, err)
assert.Empty(t, unmet)
})
t.Run("GetUnmetDependenciesForUnregisteredUnit", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// When: Unit A is requested
unmet, err := manager.GetUnmetDependencies(unitA)
// Then: a descriptive error communicates that the unit must be registered first.
require.ErrorIs(t, err, unit.ErrUnitNotFound)
assert.Nil(t, unmet)
})
}
func TestManager_MultipleDependencies(t *testing.T) {
t.Parallel()
t.Run("UnitWithMultipleDependencies", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Register all units
units := []unit.ID{unitA, unitB, unitC, unitD}
for _, unit := range units {
err := manager.Register(unit)
require.NoError(t, err)
}
// A depends on B being unit.StatusStarted AND C being "started"
err := manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
err = manager.AddDependency(unitA, unitC, unit.StatusStarted)
require.NoError(t, err)
// A should not be ready (depends on both B and C)
assert.False(t, manager.IsReady(unitA))
// Update B to unit.StatusStarted - A should still not be ready (needs C too)
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
assert.False(t, manager.IsReady(unitA))
// Update C to "started" - A should now be ready
err = manager.UpdateStatus(unitC, unit.StatusStarted)
require.NoError(t, err)
assert.True(t, manager.IsReady(unitA))
})
t.Run("ComplexDependencyChain", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Register all units
units := []unit.ID{unitA, unitB, unitC, unitD}
for _, unit := range units {
err := manager.Register(unit)
require.NoError(t, err)
}
// Create complex dependency graph:
// A depends on B being unit.StatusStarted AND C being "started"
err := manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
err = manager.AddDependency(unitA, unitC, unit.StatusStarted)
require.NoError(t, err)
// B depends on D being "completed"
err = manager.AddDependency(unitB, unitD, unit.StatusComplete)
require.NoError(t, err)
// C depends on D being "completed"
err = manager.AddDependency(unitC, unitD, unit.StatusComplete)
require.NoError(t, err)
// Initially only D is ready
assert.True(t, manager.IsReady(unitD))
assert.False(t, manager.IsReady(unitB))
assert.False(t, manager.IsReady(unitC))
assert.False(t, manager.IsReady(unitA))
// Update D to "completed" - B and C should become ready
err = manager.UpdateStatus(unitD, unit.StatusComplete)
require.NoError(t, err)
assert.True(t, manager.IsReady(unitB))
assert.True(t, manager.IsReady(unitC))
assert.False(t, manager.IsReady(unitA))
// Update B to unit.StatusStarted - A should still not be ready (needs C)
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
assert.False(t, manager.IsReady(unitA))
// Update C to "started" - A should now be ready
err = manager.UpdateStatus(unitC, unit.StatusStarted)
require.NoError(t, err)
assert.True(t, manager.IsReady(unitA))
})
t.Run("DifferentStatusTypes", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Register units
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
err = manager.Register(unitC)
require.NoError(t, err)
// Given: Unit A depends on Unit B being unit.StatusStarted
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
// Given: Unit A depends on Unit C being "completed"
err = manager.AddDependency(unitA, unitC, unit.StatusComplete)
require.NoError(t, err)
// When: Unit B is started
err = manager.UpdateStatus(unitB, unit.StatusStarted)
require.NoError(t, err)
// Then: Unit A should not be ready, because only one of its dependencies is in the desired state.
// It still requires Unit C to be completed.
assert.False(t, manager.IsReady(unitA))
// When: Unit C is completed
err = manager.UpdateStatus(unitC, unit.StatusComplete)
require.NoError(t, err)
// Then: Unit A should be ready, because both of its dependencies are in the desired state.
assert.True(t, manager.IsReady(unitA))
})
}
func TestManager_IsReady(t *testing.T) {
t.Parallel()
t.Run("IsReadyWithUnregisteredUnit", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Given: a unit is not registered
u := manager.Unit(unitA)
assert.Equal(t, unit.StatusNotRegistered, u.Status())
// Then: the unit is not ready
assert.False(t, manager.IsReady(unitA))
})
}
func TestManager_ToDOT(t *testing.T) {
t.Parallel()
t.Run("ExportSimpleGraph", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Register units
err := manager.Register(unitA)
require.NoError(t, err)
err = manager.Register(unitB)
require.NoError(t, err)
// Add dependency
err = manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
dot, err := manager.ExportDOT("test")
require.NoError(t, err)
assert.NotEmpty(t, dot)
assert.Contains(t, dot, "digraph")
})
t.Run("ExportComplexGraph", func(t *testing.T) {
t.Parallel()
manager := unit.NewManager()
// Register all units
units := []unit.ID{unitA, unitB, unitC, unitD}
for _, unit := range units {
err := manager.Register(unit)
require.NoError(t, err)
}
// Create complex dependency graph
// A depends on B and C, B depends on D, C depends on D
err := manager.AddDependency(unitA, unitB, unit.StatusStarted)
require.NoError(t, err)
err = manager.AddDependency(unitA, unitC, unit.StatusStarted)
require.NoError(t, err)
err = manager.AddDependency(unitB, unitD, unit.StatusComplete)
require.NoError(t, err)
err = manager.AddDependency(unitC, unitD, unit.StatusComplete)
require.NoError(t, err)
dot, err := manager.ExportDOT("complex")
require.NoError(t, err)
assert.NotEmpty(t, dot)
assert.Contains(t, dot, "digraph")
})
}
+45 -17
View File
@@ -11,6 +11,7 @@ import (
"os"
"path/filepath"
"runtime"
"slices"
"strconv"
"strings"
"time"
@@ -201,18 +202,15 @@ func workspaceAgent() *serpent.Command {
// Enable pprof handler
// This prevents the pprof import from being accidentally deleted.
_ = pprof.Handler
pprofSrvClose := ServeHandler(ctx, logger, nil, pprofAddress, "pprof")
defer pprofSrvClose()
if port, err := extractPort(pprofAddress); err == nil {
ignorePorts[port] = "pprof"
}
if pprofAddress != "" {
pprofSrvClose := ServeHandler(ctx, logger, nil, pprofAddress, "pprof")
defer pprofSrvClose()
if port, err := extractPort(prometheusAddress); err == nil {
ignorePorts[port] = "prometheus"
}
if port, err := extractPort(debugAddress); err == nil {
ignorePorts[port] = "debug"
if port, err := extractPort(pprofAddress); err == nil {
ignorePorts[port] = "pprof"
}
} else {
logger.Debug(ctx, "pprof address is empty, disabling pprof server")
}
executablePath, err := os.Executable()
@@ -276,6 +274,28 @@ func workspaceAgent() *serpent.Command {
for {
prometheusRegistry := prometheus.NewRegistry()
promHandler := agent.PrometheusMetricsHandler(prometheusRegistry, logger)
var serverClose []func()
if prometheusAddress != "" {
prometheusSrvClose := ServeHandler(ctx, logger, promHandler, prometheusAddress, "prometheus")
serverClose = append(serverClose, prometheusSrvClose)
if port, err := extractPort(prometheusAddress); err == nil {
ignorePorts[port] = "prometheus"
}
} else {
logger.Debug(ctx, "prometheus address is empty, disabling prometheus server")
}
if debugAddress != "" {
// ServerHandle depends on `agnt.HTTPDebug()`, but `agnt`
// depends on `ignorePorts`. Keep this if statement in sync
// with below.
if port, err := extractPort(debugAddress); err == nil {
ignorePorts[port] = "debug"
}
}
agnt := agent.New(agent.Options{
Client: client,
Logger: logger,
@@ -299,10 +319,15 @@ func workspaceAgent() *serpent.Command {
},
})
promHandler := agent.PrometheusMetricsHandler(prometheusRegistry, logger)
prometheusSrvClose := ServeHandler(ctx, logger, promHandler, prometheusAddress, "prometheus")
debugSrvClose := ServeHandler(ctx, logger, agnt.HTTPDebug(), debugAddress, "debug")
if debugAddress != "" {
// ServerHandle depends on `agnt.HTTPDebug()`, but `agnt`
// depends on `ignorePorts`. Keep this if statement in sync
// with above.
debugSrvClose := ServeHandler(ctx, logger, agnt.HTTPDebug(), debugAddress, "debug")
serverClose = append(serverClose, debugSrvClose)
} else {
logger.Debug(ctx, "debug address is empty, disabling debug server")
}
select {
case <-ctx.Done():
@@ -314,8 +339,11 @@ func workspaceAgent() *serpent.Command {
}
lastErr = agnt.Close()
debugSrvClose()
prometheusSrvClose()
slices.Reverse(serverClose)
for _, closeFunc := range serverClose {
closeFunc()
}
if mustExit {
break
+45
View File
@@ -178,6 +178,51 @@ func TestWorkspaceAgent(t *testing.T) {
require.Greater(t, atomic.LoadInt64(&called), int64(0), "expected coderd to be reached with custom headers")
require.Greater(t, atomic.LoadInt64(&derpCalled), int64(0), "expected /derp to be called with custom headers")
})
t.Run("DisabledServers", func(t *testing.T) {
t.Parallel()
client, db := coderdtest.NewWithDatabase(t, nil)
user := coderdtest.CreateFirstUser(t, client)
r := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: user.OrganizationID,
OwnerID: user.UserID,
}).WithAgent().Do()
logDir := t.TempDir()
inv, _ := clitest.New(t,
"agent",
"--auth", "token",
"--agent-token", r.AgentToken,
"--agent-url", client.URL.String(),
"--log-dir", logDir,
"--pprof-address", "",
"--prometheus-address", "",
"--debug-address", "",
)
clitest.Start(t, inv)
// Verify the agent is connected and working.
resources := coderdtest.NewWorkspaceAgentWaiter(t, client, r.Workspace.ID).
MatchResources(matchAgentWithVersion).Wait()
require.Len(t, resources, 1)
require.Len(t, resources[0].Agents, 1)
require.NotEmpty(t, resources[0].Agents[0].Version)
// Verify the servers are not listening by checking the log for disabled
// messages.
require.Eventually(t, func() bool {
logContent, err := os.ReadFile(filepath.Join(logDir, "coder-agent.log"))
if err != nil {
return false
}
logStr := string(logContent)
return strings.Contains(logStr, "pprof address is empty, disabling pprof server") &&
strings.Contains(logStr, "prometheus address is empty, disabling prometheus server") &&
strings.Contains(logStr, "debug address is empty, disabling debug server")
}, testutil.WaitLong, testutil.IntervalMedium)
})
}
func matchAgentWithVersion(rs []codersdk.WorkspaceResource) bool {
+8
View File
@@ -78,6 +78,14 @@ func NewWithCommand(
return i, configDir
}
func NewWithSDKOverride(t testing.TB, override any, args ...string) (*serpent.Invocation, config.Root) {
var root cli.RootCmd
cmd, err := root.Command(root.AGPL())
root.TestOverrideSDKClient = override
require.NoError(t, err)
return NewWithCommand(t, cmd, args...)
}
// SetupConfig applies the URL and SessionToken of the client to the config.
func SetupConfig(t *testing.T, client *codersdk.Client, root config.Root) {
err := root.Session().Write(client.SessionToken())
+48 -44
View File
@@ -577,53 +577,57 @@ func prepWorkspaceBuild(inv *serpent.Invocation, client *codersdk.Client, args p
return nil, xerrors.Errorf("template version git auth: %w", err)
}
// Run a dry-run with the given parameters to check correctness
dryRun, err := client.CreateTemplateVersionDryRun(inv.Context(), templateVersion.ID, codersdk.CreateTemplateVersionDryRunRequest{
WorkspaceName: args.NewWorkspaceName,
RichParameterValues: buildParameters,
})
if err != nil {
return nil, xerrors.Errorf("begin workspace dry-run: %w", err)
}
// Only perform dry-run for workspace creation and updates
// Skip for start and restart to avoid unnecessary delays
if args.Action == WorkspaceCreate || args.Action == WorkspaceUpdate {
// Run a dry-run with the given parameters to check correctness
dryRun, err := client.CreateTemplateVersionDryRun(inv.Context(), templateVersion.ID, codersdk.CreateTemplateVersionDryRunRequest{
WorkspaceName: args.NewWorkspaceName,
RichParameterValues: buildParameters,
})
if err != nil {
return nil, xerrors.Errorf("begin workspace dry-run: %w", err)
}
matchedProvisioners, err := client.TemplateVersionDryRunMatchedProvisioners(inv.Context(), templateVersion.ID, dryRun.ID)
if err != nil {
return nil, xerrors.Errorf("get matched provisioners: %w", err)
}
cliutil.WarnMatchedProvisioners(inv.Stdout, &matchedProvisioners, dryRun)
_, _ = fmt.Fprintln(inv.Stdout, "Planning workspace...")
err = cliui.ProvisionerJob(inv.Context(), inv.Stdout, cliui.ProvisionerJobOptions{
Fetch: func() (codersdk.ProvisionerJob, error) {
return client.TemplateVersionDryRun(inv.Context(), templateVersion.ID, dryRun.ID)
},
Cancel: func() error {
return client.CancelTemplateVersionDryRun(inv.Context(), templateVersion.ID, dryRun.ID)
},
Logs: func() (<-chan codersdk.ProvisionerJobLog, io.Closer, error) {
return client.TemplateVersionDryRunLogsAfter(inv.Context(), templateVersion.ID, dryRun.ID, 0)
},
// Don't show log output for the dry-run unless there's an error.
Silent: true,
})
if err != nil {
// TODO (Dean): reprompt for parameter values if we deem it to
// be a validation error
return nil, xerrors.Errorf("dry-run workspace: %w", err)
}
matchedProvisioners, err := client.TemplateVersionDryRunMatchedProvisioners(inv.Context(), templateVersion.ID, dryRun.ID)
if err != nil {
return nil, xerrors.Errorf("get matched provisioners: %w", err)
}
cliutil.WarnMatchedProvisioners(inv.Stdout, &matchedProvisioners, dryRun)
_, _ = fmt.Fprintln(inv.Stdout, "Planning workspace...")
err = cliui.ProvisionerJob(inv.Context(), inv.Stdout, cliui.ProvisionerJobOptions{
Fetch: func() (codersdk.ProvisionerJob, error) {
return client.TemplateVersionDryRun(inv.Context(), templateVersion.ID, dryRun.ID)
},
Cancel: func() error {
return client.CancelTemplateVersionDryRun(inv.Context(), templateVersion.ID, dryRun.ID)
},
Logs: func() (<-chan codersdk.ProvisionerJobLog, io.Closer, error) {
return client.TemplateVersionDryRunLogsAfter(inv.Context(), templateVersion.ID, dryRun.ID, 0)
},
// Don't show log output for the dry-run unless there's an error.
Silent: true,
})
if err != nil {
// TODO (Dean): reprompt for parameter values if we deem it to
// be a validation error
return nil, xerrors.Errorf("dry-run workspace: %w", err)
}
resources, err := client.TemplateVersionDryRunResources(inv.Context(), templateVersion.ID, dryRun.ID)
if err != nil {
return nil, xerrors.Errorf("get workspace dry-run resources: %w", err)
}
resources, err := client.TemplateVersionDryRunResources(inv.Context(), templateVersion.ID, dryRun.ID)
if err != nil {
return nil, xerrors.Errorf("get workspace dry-run resources: %w", err)
}
err = cliui.WorkspaceResources(inv.Stdout, resources, cliui.WorkspaceResourcesOptions{
WorkspaceName: args.NewWorkspaceName,
// Since agents haven't connected yet, hiding this makes more sense.
HideAgentState: true,
Title: "Workspace Preview",
})
if err != nil {
return nil, xerrors.Errorf("get resources: %w", err)
err = cliui.WorkspaceResources(inv.Stdout, resources, cliui.WorkspaceResourcesOptions{
WorkspaceName: args.NewWorkspaceName,
// Since agents haven't connected yet, hiding this makes more sense.
HideAgentState: true,
Title: "Workspace Preview",
})
if err != nil {
return nil, xerrors.Errorf("get resources: %w", err)
}
}
return buildParameters, nil
+88 -59
View File
@@ -64,7 +64,9 @@ func (r *RootCmd) scaletestCmd() *serpent.Command {
r.scaletestWorkspaceTraffic(),
r.scaletestAutostart(),
r.scaletestNotifications(),
r.scaletestTaskStatus(),
r.scaletestSMTP(),
r.scaletestPrebuilds(),
},
}
@@ -384,6 +386,88 @@ func (s *scaletestPrometheusFlags) attach(opts *serpent.OptionSet) {
)
}
// workspaceTargetFlags holds common flags for targeting specific workspaces in scale tests.
type workspaceTargetFlags struct {
template string
targetWorkspaces string
useHostLogin bool
}
// attach adds the workspace target flags to the given options set.
func (f *workspaceTargetFlags) attach(opts *serpent.OptionSet) {
*opts = append(*opts,
serpent.Option{
Flag: "template",
FlagShorthand: "t",
Env: "CODER_SCALETEST_TEMPLATE",
Description: "Name or ID of the template. Traffic generation will be limited to workspaces created from this template.",
Value: serpent.StringOf(&f.template),
},
serpent.Option{
Flag: "target-workspaces",
Env: "CODER_SCALETEST_TARGET_WORKSPACES",
Description: "Target a specific range of workspaces in the format [START]:[END] (exclusive). Example: 0:10 will target the 10 first alphabetically sorted workspaces (0-9).",
Value: serpent.StringOf(&f.targetWorkspaces),
},
serpent.Option{
Flag: "use-host-login",
Env: "CODER_SCALETEST_USE_HOST_LOGIN",
Default: "false",
Description: "Connect as the currently logged in user.",
Value: serpent.BoolOf(&f.useHostLogin),
},
)
}
// getTargetedWorkspaces retrieves the workspaces based on the template filter and target range. warnWriter is where to
// write a warning message if any workspaces were skipped due to ownership mismatch.
func (f *workspaceTargetFlags) getTargetedWorkspaces(ctx context.Context, client *codersdk.Client, organizationIDs []uuid.UUID, warnWriter io.Writer) ([]codersdk.Workspace, error) {
// Validate template if provided
if f.template != "" {
_, err := parseTemplate(ctx, client, organizationIDs, f.template)
if err != nil {
return nil, xerrors.Errorf("parse template: %w", err)
}
}
// Parse target range
targetStart, targetEnd, err := parseTargetRange("workspaces", f.targetWorkspaces)
if err != nil {
return nil, xerrors.Errorf("parse target workspaces: %w", err)
}
// Determine owner based on useHostLogin
var owner string
if f.useHostLogin {
owner = codersdk.Me
}
// Get workspaces
workspaces, numSkipped, err := getScaletestWorkspaces(ctx, client, owner, f.template)
if err != nil {
return nil, err
}
if numSkipped > 0 {
cliui.Warnf(warnWriter, "CODER_DISABLE_OWNER_WORKSPACE_ACCESS is set on the deployment.\n\t%d workspace(s) were skipped due to ownership mismatch.\n\tSet --use-host-login to only target workspaces you own.", numSkipped)
}
// Adjust targetEnd if not specified
if targetEnd == 0 {
targetEnd = len(workspaces)
}
// Validate range
if len(workspaces) == 0 {
return nil, xerrors.Errorf("no scaletest workspaces exist")
}
if targetEnd > len(workspaces) {
return nil, xerrors.Errorf("target workspace end %d is greater than the number of workspaces %d", targetEnd, len(workspaces))
}
// Return the sliced workspaces
return workspaces[targetStart:targetEnd], nil
}
func requireAdmin(ctx context.Context, client *codersdk.Client) (codersdk.User, error) {
me, err := client.User(ctx, codersdk.Me)
if err != nil {
@@ -1193,12 +1277,10 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
bytesPerTick int64
ssh bool
disableDirect bool
useHostLogin bool
app string
template string
targetWorkspaces string
workspaceProxyURL string
targetFlags = &workspaceTargetFlags{}
tracingFlags = &scaletestTracingFlags{}
strategy = &scaletestStrategyFlags{}
cleanupStrategy = newScaletestCleanupStrategy()
@@ -1243,15 +1325,9 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
},
}
if template != "" {
_, err := parseTemplate(ctx, client, me.OrganizationIDs, template)
if err != nil {
return xerrors.Errorf("parse template: %w", err)
}
}
targetWorkspaceStart, targetWorkspaceEnd, err := parseTargetRange("workspaces", targetWorkspaces)
workspaces, err := targetFlags.getTargetedWorkspaces(ctx, client, me.OrganizationIDs, inv.Stdout)
if err != nil {
return xerrors.Errorf("parse target workspaces: %w", err)
return err
}
appHost, err := client.AppHost(ctx)
@@ -1259,30 +1335,6 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
return xerrors.Errorf("get app host: %w", err)
}
var owner string
if useHostLogin {
owner = codersdk.Me
}
workspaces, numSkipped, err := getScaletestWorkspaces(inv.Context(), client, owner, template)
if err != nil {
return err
}
if numSkipped > 0 {
cliui.Warnf(inv.Stdout, "CODER_DISABLE_OWNER_WORKSPACE_ACCESS is set on the deployment.\n\t%d workspace(s) were skipped due to ownership mismatch.\n\tSet --use-host-login to only target workspaces you own.", numSkipped)
}
if targetWorkspaceEnd == 0 {
targetWorkspaceEnd = len(workspaces)
}
if len(workspaces) == 0 {
return xerrors.Errorf("no scaletest workspaces exist")
}
if targetWorkspaceEnd > len(workspaces) {
return xerrors.Errorf("target workspace end %d is greater than the number of workspaces %d", targetWorkspaceEnd, len(workspaces))
}
tracerProvider, closeTracing, tracingEnabled, err := tracingFlags.provider(ctx)
if err != nil {
return xerrors.Errorf("create tracer provider: %w", err)
@@ -1307,10 +1359,6 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
th := harness.NewTestHarness(strategy.toStrategy(), cleanupStrategy.toStrategy())
for idx, ws := range workspaces {
if idx < targetWorkspaceStart || idx >= targetWorkspaceEnd {
continue
}
var (
agent codersdk.WorkspaceAgent
name = "workspace-traffic"
@@ -1415,19 +1463,6 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
}
cmd.Options = []serpent.Option{
{
Flag: "template",
FlagShorthand: "t",
Env: "CODER_SCALETEST_TEMPLATE",
Description: "Name or ID of the template. Traffic generation will be limited to workspaces created from this template.",
Value: serpent.StringOf(&template),
},
{
Flag: "target-workspaces",
Env: "CODER_SCALETEST_TARGET_WORKSPACES",
Description: "Target a specific range of workspaces in the format [START]:[END] (exclusive). Example: 0:10 will target the 10 first alphabetically sorted workspaces (0-9).",
Value: serpent.StringOf(&targetWorkspaces),
},
{
Flag: "bytes-per-tick",
Env: "CODER_SCALETEST_WORKSPACE_TRAFFIC_BYTES_PER_TICK",
@@ -1463,13 +1498,6 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
Description: "Send WebSocket traffic to a workspace app (proxied via coderd), cannot be used with --ssh.",
Value: serpent.StringOf(&app),
},
{
Flag: "use-host-login",
Env: "CODER_SCALETEST_USE_HOST_LOGIN",
Default: "false",
Description: "Connect as the currently logged in user.",
Value: serpent.BoolOf(&useHostLogin),
},
{
Flag: "workspace-proxy-url",
Env: "CODER_SCALETEST_WORKSPACE_PROXY_URL",
@@ -1479,6 +1507,7 @@ func (r *RootCmd) scaletestWorkspaceTraffic() *serpent.Command {
},
}
targetFlags.attach(&cmd.Options)
tracingFlags.attach(&cmd.Options)
strategy.attach(&cmd.Options)
cleanupStrategy.attach(&cmd.Options)
+76 -53
View File
@@ -3,6 +3,7 @@
package cli
import (
"bytes"
"context"
"fmt"
"net/http"
@@ -29,12 +30,13 @@ import (
func (r *RootCmd) scaletestNotifications() *serpent.Command {
var (
userCount int64
ownerUserPercentage float64
notificationTimeout time.Duration
dialTimeout time.Duration
noCleanup bool
smtpAPIURL string
userCount int64
templateAdminPercentage float64
notificationTimeout time.Duration
smtpRequestTimeout time.Duration
dialTimeout time.Duration
noCleanup bool
smtpAPIURL string
tracingFlags = &scaletestTracingFlags{}
@@ -77,24 +79,24 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
return xerrors.Errorf("--user-count must be greater than 0")
}
if ownerUserPercentage < 0 || ownerUserPercentage > 100 {
return xerrors.Errorf("--owner-user-percentage must be between 0 and 100")
if templateAdminPercentage < 0 || templateAdminPercentage > 100 {
return xerrors.Errorf("--template-admin-percentage must be between 0 and 100")
}
if smtpAPIURL != "" && !strings.HasPrefix(smtpAPIURL, "http://") && !strings.HasPrefix(smtpAPIURL, "https://") {
return xerrors.Errorf("--smtp-api-url must start with http:// or https://")
}
ownerUserCount := int64(float64(userCount) * ownerUserPercentage / 100)
if ownerUserCount == 0 && ownerUserPercentage > 0 {
ownerUserCount = 1
templateAdminCount := int64(float64(userCount) * templateAdminPercentage / 100)
if templateAdminCount == 0 && templateAdminPercentage > 0 {
templateAdminCount = 1
}
regularUserCount := userCount - ownerUserCount
regularUserCount := userCount - templateAdminCount
_, _ = fmt.Fprintf(inv.Stderr, "Distribution plan:\n")
_, _ = fmt.Fprintf(inv.Stderr, " Total users: %d\n", userCount)
_, _ = fmt.Fprintf(inv.Stderr, " Owner users: %d (%.1f%%)\n", ownerUserCount, ownerUserPercentage)
_, _ = fmt.Fprintf(inv.Stderr, " Regular users: %d (%.1f%%)\n", regularUserCount, 100.0-ownerUserPercentage)
_, _ = fmt.Fprintf(inv.Stderr, " Template admins: %d (%.1f%%)\n", templateAdminCount, templateAdminPercentage)
_, _ = fmt.Fprintf(inv.Stderr, " Regular users: %d (%.1f%%)\n", regularUserCount, 100.0-templateAdminPercentage)
outputs, err := output.parse()
if err != nil {
@@ -127,13 +129,12 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
_, _ = fmt.Fprintln(inv.Stderr, "Creating users...")
dialBarrier := &sync.WaitGroup{}
ownerWatchBarrier := &sync.WaitGroup{}
templateAdminWatchBarrier := &sync.WaitGroup{}
dialBarrier.Add(int(userCount))
ownerWatchBarrier.Add(int(ownerUserCount))
templateAdminWatchBarrier.Add(int(templateAdminCount))
expectedNotificationIDs := map[uuid.UUID]struct{}{
notificationsLib.TemplateUserAccountCreated: {},
notificationsLib.TemplateUserAccountDeleted: {},
notificationsLib.TemplateTemplateDeleted: {},
}
triggerTimes := make(map[uuid.UUID]chan time.Time, len(expectedNotificationIDs))
@@ -142,19 +143,20 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
}
configs := make([]notifications.Config, 0, userCount)
for range ownerUserCount {
for range templateAdminCount {
config := notifications.Config{
User: createusers.Config{
OrganizationID: me.OrganizationIDs[0],
},
Roles: []string{codersdk.RoleOwner},
Roles: []string{codersdk.RoleTemplateAdmin},
NotificationTimeout: notificationTimeout,
DialTimeout: dialTimeout,
DialBarrier: dialBarrier,
ReceivingWatchBarrier: ownerWatchBarrier,
ReceivingWatchBarrier: templateAdminWatchBarrier,
ExpectedNotificationsIDs: expectedNotificationIDs,
Metrics: metrics,
SMTPApiURL: smtpAPIURL,
SMTPRequestTimeout: smtpRequestTimeout,
}
if err := config.Validate(); err != nil {
return xerrors.Errorf("validate config: %w", err)
@@ -170,9 +172,8 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
NotificationTimeout: notificationTimeout,
DialTimeout: dialTimeout,
DialBarrier: dialBarrier,
ReceivingWatchBarrier: ownerWatchBarrier,
ReceivingWatchBarrier: templateAdminWatchBarrier,
Metrics: metrics,
SMTPApiURL: smtpAPIURL,
}
if err := config.Validate(); err != nil {
return xerrors.Errorf("validate config: %w", err)
@@ -180,7 +181,7 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
configs = append(configs, config)
}
go triggerUserNotifications(
go triggerNotifications(
ctx,
logger,
client,
@@ -261,23 +262,30 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
Required: true,
},
{
Flag: "owner-user-percentage",
Env: "CODER_SCALETEST_NOTIFICATION_OWNER_USER_PERCENTAGE",
Flag: "template-admin-percentage",
Env: "CODER_SCALETEST_NOTIFICATION_TEMPLATE_ADMIN_PERCENTAGE",
Default: "20.0",
Description: "Percentage of users to assign Owner role to (0-100).",
Value: serpent.Float64Of(&ownerUserPercentage),
Description: "Percentage of users to assign Template Admin role to (0-100).",
Value: serpent.Float64Of(&templateAdminPercentage),
},
{
Flag: "notification-timeout",
Env: "CODER_SCALETEST_NOTIFICATION_TIMEOUT",
Default: "5m",
Default: "10m",
Description: "How long to wait for notifications after triggering.",
Value: serpent.DurationOf(&notificationTimeout),
},
{
Flag: "smtp-request-timeout",
Env: "CODER_SCALETEST_SMTP_REQUEST_TIMEOUT",
Default: "5m",
Description: "Timeout for SMTP requests.",
Value: serpent.DurationOf(&smtpRequestTimeout),
},
{
Flag: "dial-timeout",
Env: "CODER_SCALETEST_DIAL_TIMEOUT",
Default: "2m",
Default: "10m",
Description: "Timeout for dialing the notification websocket endpoint.",
Value: serpent.DurationOf(&dialTimeout),
},
@@ -379,9 +387,9 @@ func computeNotificationLatencies(
return nil
}
// triggerUserNotifications waits for all test users to connect,
// then creates and deletes a test user to trigger notification events for testing.
func triggerUserNotifications(
// triggerNotifications waits for all test users to connect,
// then creates and deletes a test template to trigger notification events for testing.
func triggerNotifications(
ctx context.Context,
logger slog.Logger,
client *codersdk.Client,
@@ -414,34 +422,49 @@ func triggerUserNotifications(
return
}
const (
triggerUsername = "scaletest-trigger-user"
triggerEmail = "scaletest-trigger@example.com"
)
logger.Info(ctx, "creating test template to test notifications")
logger.Info(ctx, "creating test user to test notifications",
slog.F("username", triggerUsername),
slog.F("email", triggerEmail),
slog.F("org_id", orgID))
// Upload empty template file.
file, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader([]byte{}))
if err != nil {
logger.Error(ctx, "upload test template", slog.Error(err))
return
}
logger.Info(ctx, "test template uploaded", slog.F("file_id", file.ID))
testUser, err := client.CreateUserWithOrgs(ctx, codersdk.CreateUserRequestWithOrgs{
OrganizationIDs: []uuid.UUID{orgID},
Username: triggerUsername,
Email: triggerEmail,
Password: "test-password-123",
// Create template version.
version, err := client.CreateTemplateVersion(ctx, orgID, codersdk.CreateTemplateVersionRequest{
StorageMethod: codersdk.ProvisionerStorageMethodFile,
FileID: file.ID,
Provisioner: codersdk.ProvisionerTypeEcho,
})
if err != nil {
logger.Error(ctx, "create test user", slog.Error(err))
logger.Error(ctx, "create test template version", slog.Error(err))
return
}
expectedNotifications[notificationsLib.TemplateUserAccountCreated] <- time.Now()
logger.Info(ctx, "test template version created", slog.F("template_version_id", version.ID))
err = client.DeleteUser(ctx, testUser.ID)
// Create template.
testTemplate, err := client.CreateTemplate(ctx, orgID, codersdk.CreateTemplateRequest{
Name: "scaletest-test-template",
Description: "scaletest-test-template",
VersionID: version.ID,
})
if err != nil {
logger.Error(ctx, "delete test user", slog.Error(err))
logger.Error(ctx, "create test template", slog.Error(err))
return
}
expectedNotifications[notificationsLib.TemplateUserAccountDeleted] <- time.Now()
close(expectedNotifications[notificationsLib.TemplateUserAccountCreated])
close(expectedNotifications[notificationsLib.TemplateUserAccountDeleted])
logger.Info(ctx, "test template created", slog.F("template_id", testTemplate.ID))
// Delete template to trigger notification.
err = client.DeleteTemplate(ctx, testTemplate.ID)
if err != nil {
logger.Error(ctx, "delete test template", slog.Error(err))
return
}
logger.Info(ctx, "test template deleted", slog.F("template_id", testTemplate.ID))
// Record expected notification.
expectedNotifications[notificationsLib.TemplateTemplateDeleted] <- time.Now()
close(expectedNotifications[notificationsLib.TemplateTemplateDeleted])
}
+297
View File
@@ -0,0 +1,297 @@
//go:build !slim
package cli
import (
"fmt"
"net/http"
"os/signal"
"strconv"
"sync"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/scaletest/harness"
"github.com/coder/coder/v2/scaletest/prebuilds"
"github.com/coder/quartz"
"github.com/coder/serpent"
)
func (r *RootCmd) scaletestPrebuilds() *serpent.Command {
var (
numTemplates int64
numPresets int64
numPresetPrebuilds int64
templateVersionJobTimeout time.Duration
prebuildWorkspaceTimeout time.Duration
noCleanup bool
tracingFlags = &scaletestTracingFlags{}
timeoutStrategy = &timeoutFlags{}
cleanupStrategy = newScaletestCleanupStrategy()
output = &scaletestOutputFlags{}
prometheusFlags = &scaletestPrometheusFlags{}
)
cmd := &serpent.Command{
Use: "prebuilds",
Short: "Creates prebuild workspaces on the Coder server.",
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
client, err := r.InitClient(inv)
if err != nil {
return err
}
notifyCtx, stop := signal.NotifyContext(ctx, StopSignals...)
defer stop()
ctx = notifyCtx
me, err := requireAdmin(ctx, client)
if err != nil {
return err
}
client.HTTPClient = &http.Client{
Transport: &codersdk.HeaderTransport{
Transport: http.DefaultTransport,
Header: map[string][]string{
codersdk.BypassRatelimitHeader: {"true"},
},
},
}
if numTemplates <= 0 {
return xerrors.Errorf("--num-templates must be greater than 0")
}
if numPresets <= 0 {
return xerrors.Errorf("--num-presets must be greater than 0")
}
if numPresetPrebuilds <= 0 {
return xerrors.Errorf("--num-preset-prebuilds must be greater than 0")
}
outputs, err := output.parse()
if err != nil {
return xerrors.Errorf("parse output flags: %w", err)
}
tracerProvider, closeTracing, tracingEnabled, err := tracingFlags.provider(ctx)
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()
metrics := prebuilds.NewMetrics(reg)
logger := inv.Logger
prometheusSrvClose := ServeHandler(ctx, logger, promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), prometheusFlags.Address, "prometheus")
defer prometheusSrvClose()
err = client.PutPrebuildsSettings(ctx, codersdk.PrebuildsSettings{
ReconciliationPaused: true,
})
if err != nil {
return xerrors.Errorf("pause prebuilds: %w", err)
}
setupBarrier := new(sync.WaitGroup)
setupBarrier.Add(int(numTemplates))
creationBarrier := new(sync.WaitGroup)
creationBarrier.Add(int(numTemplates))
deletionSetupBarrier := new(sync.WaitGroup)
deletionSetupBarrier.Add(1)
deletionBarrier := new(sync.WaitGroup)
deletionBarrier.Add(int(numTemplates))
th := harness.NewTestHarness(timeoutStrategy.wrapStrategy(harness.ConcurrentExecutionStrategy{}), cleanupStrategy.toStrategy())
for i := range numTemplates {
id := strconv.Itoa(int(i))
cfg := prebuilds.Config{
OrganizationID: me.OrganizationIDs[0],
NumPresets: int(numPresets),
NumPresetPrebuilds: int(numPresetPrebuilds),
TemplateVersionJobTimeout: templateVersionJobTimeout,
PrebuildWorkspaceTimeout: prebuildWorkspaceTimeout,
Metrics: metrics,
SetupBarrier: setupBarrier,
CreationBarrier: creationBarrier,
DeletionSetupBarrier: deletionSetupBarrier,
DeletionBarrier: deletionBarrier,
Clock: quartz.NewReal(),
}
err := cfg.Validate()
if err != nil {
return xerrors.Errorf("validate config: %w", err)
}
var runner harness.Runnable = prebuilds.NewRunner(client, cfg)
if tracingEnabled {
runner = &runnableTraceWrapper{
tracer: tracer,
spanName: fmt.Sprintf("prebuilds/%s", id),
runner: runner,
}
}
th.AddRun("prebuilds", id, runner)
}
_, _ = fmt.Fprintf(inv.Stderr, "Creating %d templates with %d presets and %d prebuilds per preset...\n",
numTemplates, numPresets, numPresetPrebuilds)
_, _ = fmt.Fprintf(inv.Stderr, "Total expected prebuilds: %d\n", numTemplates*numPresets*numPresetPrebuilds)
testCtx, testCancel := timeoutStrategy.toContext(ctx)
defer testCancel()
runErrCh := make(chan error, 1)
go func() {
runErrCh <- th.Run(testCtx)
}()
_, _ = fmt.Fprintln(inv.Stderr, "Waiting for all templates to be created...")
setupBarrier.Wait()
_, _ = fmt.Fprintln(inv.Stderr, "All templates created")
err = client.PutPrebuildsSettings(ctx, codersdk.PrebuildsSettings{
ReconciliationPaused: false,
})
if err != nil {
return xerrors.Errorf("resume prebuilds: %w", err)
}
_, _ = fmt.Fprintln(inv.Stderr, "Waiting for all prebuilds to be created...")
creationBarrier.Wait()
_, _ = fmt.Fprintln(inv.Stderr, "All prebuilds created")
err = client.PutPrebuildsSettings(ctx, codersdk.PrebuildsSettings{
ReconciliationPaused: true,
})
if err != nil {
return xerrors.Errorf("pause prebuilds before deletion: %w", err)
}
_, _ = fmt.Fprintln(inv.Stderr, "Prebuilds paused, signaling runners to prepare for deletion")
deletionSetupBarrier.Done()
_, _ = fmt.Fprintln(inv.Stderr, "Waiting for all templates to be updated with 0 prebuilds...")
deletionBarrier.Wait()
_, _ = fmt.Fprintln(inv.Stderr, "All templates updated")
err = client.PutPrebuildsSettings(ctx, codersdk.PrebuildsSettings{
ReconciliationPaused: false,
})
if err != nil {
return xerrors.Errorf("resume prebuilds for deletion: %w", err)
}
_, _ = fmt.Fprintln(inv.Stderr, "Waiting for all prebuilds to be deleted...")
err = <-runErrCh
if err != nil {
return xerrors.Errorf("run test harness (harness failure, not a test failure): %w", err)
}
// If the command was interrupted, skip cleanup & stats
if notifyCtx.Err() != nil {
return notifyCtx.Err()
}
res := th.Results()
for _, o := range outputs {
err = o.write(res, inv.Stdout)
if err != nil {
return xerrors.Errorf("write output %q to %q: %w", o.format, o.path, err)
}
}
if !noCleanup {
_, _ = fmt.Fprintln(inv.Stderr, "\nStarting cleanup (deleting templates)...")
cleanupCtx, cleanupCancel := cleanupStrategy.toContext(ctx)
defer cleanupCancel()
err = th.Cleanup(cleanupCtx)
if err != nil {
return xerrors.Errorf("cleanup tests: %w", err)
}
// If the cleanup was interrupted, skip stats
if notifyCtx.Err() != nil {
return notifyCtx.Err()
}
}
if res.TotalFail > 0 {
return xerrors.New("prebuild creation test failed, see above for more details")
}
return nil
},
}
cmd.Options = serpent.OptionSet{
{
Flag: "num-templates",
Env: "CODER_SCALETEST_PREBUILDS_NUM_TEMPLATES",
Default: "1",
Description: "Number of templates to create for the test.",
Value: serpent.Int64Of(&numTemplates),
},
{
Flag: "num-presets",
Env: "CODER_SCALETEST_PREBUILDS_NUM_PRESETS",
Default: "1",
Description: "Number of presets per template.",
Value: serpent.Int64Of(&numPresets),
},
{
Flag: "num-preset-prebuilds",
Env: "CODER_SCALETEST_PREBUILDS_NUM_PRESET_PREBUILDS",
Default: "1",
Description: "Number of prebuilds per preset.",
Value: serpent.Int64Of(&numPresetPrebuilds),
},
{
Flag: "template-version-job-timeout",
Env: "CODER_SCALETEST_PREBUILDS_TEMPLATE_VERSION_JOB_TIMEOUT",
Default: "5m",
Description: "Timeout for template version provisioning jobs.",
Value: serpent.DurationOf(&templateVersionJobTimeout),
},
{
Flag: "prebuild-workspace-timeout",
Env: "CODER_SCALETEST_PREBUILDS_WORKSPACE_TIMEOUT",
Default: "10m",
Description: "Timeout for all prebuild workspaces to be created/deleted.",
Value: serpent.DurationOf(&prebuildWorkspaceTimeout),
},
{
Flag: "skip-cleanup",
Env: "CODER_SCALETEST_PREBUILDS_SKIP_CLEANUP",
Description: "Skip cleanup (deletion test) and leave resources intact.",
Value: serpent.BoolOf(&noCleanup),
},
}
tracingFlags.attach(&cmd.Options)
timeoutStrategy.attach(&cmd.Options)
cleanupStrategy.attach(&cmd.Options)
output.attach(&cmd.Options)
prometheusFlags.attach(&cmd.Options)
return cmd
}
+275
View File
@@ -0,0 +1,275 @@
//go:build !slim
package cli
import (
"context"
"fmt"
"net/http"
"sync"
"time"
"github.com/google/uuid"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"golang.org/x/xerrors"
"cdr.dev/slog"
"cdr.dev/slog/sloggers/sloghuman"
"github.com/coder/serpent"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/scaletest/harness"
"github.com/coder/coder/v2/scaletest/taskstatus"
)
const (
taskStatusTestName = "task-status"
)
func (r *RootCmd) scaletestTaskStatus() *serpent.Command {
var (
count int64
template string
workspaceNamePrefix string
appSlug string
reportStatusPeriod time.Duration
reportStatusDuration time.Duration
baselineDuration time.Duration
tracingFlags = &scaletestTracingFlags{}
prometheusFlags = &scaletestPrometheusFlags{}
timeoutStrategy = &timeoutFlags{}
cleanupStrategy = newScaletestCleanupStrategy()
output = &scaletestOutputFlags{}
)
orgContext := NewOrganizationContext()
cmd := &serpent.Command{
Use: "task-status",
Short: "Generates load on the Coder server by simulating task status reporting",
Long: `This test creates external workspaces and simulates AI agents reporting task status.
After all runners connect, it waits for the baseline duration before triggering status reporting.`,
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
outputs, err := output.parse()
if err != nil {
return xerrors.Errorf("could not parse --output flags: %w", err)
}
client, err := r.InitClient(inv)
if err != nil {
return err
}
org, err := orgContext.Selected(inv, client)
if err != nil {
return err
}
_, err = requireAdmin(ctx, client)
if err != nil {
return err
}
// Disable rate limits for this test
client.HTTPClient = &http.Client{
Transport: &codersdk.HeaderTransport{
Transport: http.DefaultTransport,
Header: map[string][]string{
codersdk.BypassRatelimitHeader: {"true"},
},
},
}
// Find the template
tpl, err := parseTemplate(ctx, client, []uuid.UUID{org.ID}, template)
if err != nil {
return xerrors.Errorf("parse template %q: %w", template, err)
}
templateID := tpl.ID
reg := prometheus.NewRegistry()
metrics := taskstatus.NewMetrics(reg)
logger := slog.Make(sloghuman.Sink(inv.Stdout)).Leveled(slog.LevelDebug)
prometheusSrvClose := ServeHandler(ctx, logger, promhttp.HandlerFor(reg, promhttp.HandlerOpts{}), prometheusFlags.Address, "prometheus")
defer prometheusSrvClose()
tracerProvider, closeTracing, tracingEnabled, err := tracingFlags.provider(ctx)
if err != nil {
return xerrors.Errorf("create tracer provider: %w", err)
}
defer func() {
// Allow time for traces to flush even if command context is
// canceled. This is a no-op if tracing is not enabled.
_, _ = fmt.Fprintln(inv.Stderr, "\nUploading traces...")
if err := closeTracing(ctx); err != nil {
_, _ = fmt.Fprintf(inv.Stderr, "\nError uploading traces: %+v\n", err)
}
// Wait for prometheus metrics to be scraped
_, _ = fmt.Fprintf(inv.Stderr, "Waiting %s for prometheus metrics to be scraped\n", prometheusFlags.Wait)
<-time.After(prometheusFlags.Wait)
}()
tracer := tracerProvider.Tracer(scaletestTracerName)
// Setup shared resources for coordination
connectedWaitGroup := &sync.WaitGroup{}
connectedWaitGroup.Add(int(count))
startReporting := make(chan struct{})
// Create the test harness
th := harness.NewTestHarness(
timeoutStrategy.wrapStrategy(harness.ConcurrentExecutionStrategy{}),
cleanupStrategy.toStrategy(),
)
// Create runners
for i := range count {
workspaceName := fmt.Sprintf("%s-%d", workspaceNamePrefix, i)
cfg := taskstatus.Config{
TemplateID: templateID,
WorkspaceName: workspaceName,
AppSlug: appSlug,
ConnectedWaitGroup: connectedWaitGroup,
StartReporting: startReporting,
ReportStatusPeriod: reportStatusPeriod,
ReportStatusDuration: reportStatusDuration,
Metrics: metrics,
MetricLabelValues: []string{},
}
if err := cfg.Validate(); err != nil {
return xerrors.Errorf("validate config for runner %d: %w", i, err)
}
var runner harness.Runnable = taskstatus.NewRunner(client, cfg)
if tracingEnabled {
runner = &runnableTraceWrapper{
tracer: tracer,
spanName: fmt.Sprintf("%s/%d", taskStatusTestName, i),
runner: runner,
}
}
th.AddRun(taskStatusTestName, workspaceName, runner)
}
// Start the test in a separate goroutine so we can coordinate timing
testCtx, testCancel := timeoutStrategy.toContext(ctx)
defer testCancel()
testDone := make(chan error)
go func() {
testDone <- th.Run(testCtx)
}()
// Wait for all runners to connect
logger.Info(ctx, "waiting for all runners to connect")
waitCtx, waitCancel := context.WithTimeout(ctx, 5*time.Minute)
defer waitCancel()
connectDone := make(chan struct{})
go func() {
connectedWaitGroup.Wait()
close(connectDone)
}()
select {
case <-waitCtx.Done():
return xerrors.Errorf("timeout waiting for runners to connect")
case <-connectDone:
logger.Info(ctx, "all runners connected")
}
// Wait for baseline duration
logger.Info(ctx, "waiting for baseline duration", slog.F("duration", baselineDuration))
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(baselineDuration):
}
// Trigger all runners to start reporting
logger.Info(ctx, "triggering runners to start reporting task status")
close(startReporting)
// Wait for the test to complete
err = <-testDone
if err != nil {
return xerrors.Errorf("run test harness: %w", err)
}
res := th.Results()
for _, o := range outputs {
err = o.write(res, inv.Stdout)
if err != nil {
return xerrors.Errorf("write output %q to %q: %w", o.format, o.path, err)
}
}
cleanupCtx, cleanupCancel := cleanupStrategy.toContext(ctx)
defer cleanupCancel()
err = th.Cleanup(cleanupCtx)
if err != nil {
return xerrors.Errorf("cleanup tests: %w", err)
}
if res.TotalFail > 0 {
return xerrors.New("load test failed, see above for more details")
}
return nil
},
}
cmd.Options = serpent.OptionSet{
{
Flag: "count",
Description: "Number of concurrent runners to create.",
Default: "10",
Value: serpent.Int64Of(&count),
},
{
Flag: "template",
Description: "Name or UUID of the template to use for the scale test. The template MUST include a coder_external_agent and a coder_app.",
Default: "scaletest-task-status",
Value: serpent.StringOf(&template),
},
{
Flag: "workspace-name-prefix",
Description: "Prefix for workspace names (will be suffixed with index).",
Default: "scaletest-task-status",
Value: serpent.StringOf(&workspaceNamePrefix),
},
{
Flag: "app-slug",
Description: "Slug of the app designated as the AI Agent.",
Default: "ai-agent",
Value: serpent.StringOf(&appSlug),
},
{
Flag: "report-status-period",
Description: "Time between reporting task statuses.",
Default: "10s",
Value: serpent.DurationOf(&reportStatusPeriod),
},
{
Flag: "report-status-duration",
Description: "Total time to report task statuses after baseline.",
Default: "15m",
Value: serpent.DurationOf(&reportStatusDuration),
},
{
Flag: "baseline-duration",
Description: "Duration to wait after all runners connect before starting to report status.",
Default: "10m",
Value: serpent.DurationOf(&baselineDuration),
},
}
orgContext.AttachOptions(cmd)
output.attach(&cmd.Options)
tracingFlags.attach(&cmd.Options)
prometheusFlags.attach(&cmd.Options)
timeoutStrategy.attach(&cmd.Options)
cleanupStrategy.attach(&cmd.Options)
return cmd
}
+18 -35
View File
@@ -56,19 +56,14 @@ 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" && r.URL.Query().Get("q") == "owner:\"me\"":
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/exists":
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
}{
Tasks: []codersdk.Task{{
httpapi.Write(r.Context(), w, http.StatusOK,
codersdk.Task{
ID: taskID,
Name: "exists",
OwnerName: "me",
}},
Count: 1,
})
})
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id1:
c.deleteCalls.Add(1)
w.WriteHeader(http.StatusAccepted)
@@ -107,27 +102,21 @@ func TestExpTaskDelete(t *testing.T) {
name: "Multiple_YesFlag",
args: []string{"--yes", "first", id4},
buildHandler: func(c *testCounters) http.HandlerFunc {
firstID := uuid.MustParse(id3)
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/experimental/tasks/me/first":
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
}{
Tasks: []codersdk.Task{{
ID: firstID,
Name: "first",
OwnerName: "me",
}},
Count: 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:
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse(id4),
OwnerName: "me",
Name: "uuid-task-2",
Name: "uuid-task-4",
})
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/"+id3:
c.deleteCalls.Add(1)
@@ -141,7 +130,7 @@ func TestExpTaskDelete(t *testing.T) {
}
},
wantDeleteCalls: 2,
wantNameResolves: 1,
wantNameResolves: 2,
wantDeletedMessage: 2,
},
{
@@ -174,20 +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" && r.URL.Query().Get("q") == "owner:\"me\"":
case r.Method == http.MethodGet && r.URL.Path == "/api/experimental/tasks/me/bad":
c.nameResolves.Add(1)
httpapi.Write(r.Context(), w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
}{
Tasks: []codersdk.Task{{
ID: taskID,
Name: "bad",
OwnerName: "me",
}},
Count: 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/"+id5:
case r.Method == http.MethodDelete && r.URL.Path == "/api/experimental/tasks/me/bad":
httpapi.InternalServerError(w, xerrors.New("boom"))
default:
httpapi.InternalServerError(w, xerrors.New("unwanted path: "+r.Method+" "+r.URL.Path))
+9 -67
View File
@@ -2,7 +2,6 @@ package cli_test
import (
"bytes"
"context"
"database/sql"
"encoding/json"
"io"
@@ -19,10 +18,7 @@ import (
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbauthz"
"github.com/coder/coder/v2/coderd/database/dbfake"
"github.com/coder/coder/v2/coderd/database/dbgen"
"github.com/coder/coder/v2/coderd/database/dbtime"
"github.com/coder/coder/v2/coderd/util/slice"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
@@ -43,76 +39,22 @@ func makeAITask(t *testing.T, db database.Store, orgID, adminID, ownerID uuid.UU
},
}).Do()
ws := database.WorkspaceTable{
build := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: orgID,
OwnerID: ownerID,
TemplateID: tv.Template.ID,
}
build := dbfake.WorkspaceBuild(t, db, ws).
}).
Seed(database.WorkspaceBuild{
TemplateVersionID: tv.TemplateVersion.ID,
Transition: transition,
}).WithAgent().Do()
dbgen.WorkspaceBuildParameters(t, db, []database.WorkspaceBuildParameter{
{
WorkspaceBuildID: build.Build.ID,
Name: codersdk.AITaskPromptParameterName,
Value: prompt,
},
})
agents, err := db.GetWorkspaceAgentsByWorkspaceAndBuildNumber(
dbauthz.AsSystemRestricted(context.Background()),
database.GetWorkspaceAgentsByWorkspaceAndBuildNumberParams{
WorkspaceID: build.Workspace.ID,
BuildNumber: build.Build.BuildNumber,
},
)
require.NoError(t, err)
require.NotEmpty(t, agents)
agentID := agents[0].ID
}).
WithAgent().
WithTask(database.TaskTable{
Prompt: prompt,
}, nil).
Do()
// Create a workspace app and set it as the sidebar app.
app := dbgen.WorkspaceApp(t, db, database.WorkspaceApp{
AgentID: agentID,
Slug: "task-sidebar",
DisplayName: "Task Sidebar",
External: false,
})
// Update build flags to reference the sidebar app and HasAITask=true.
err = db.UpdateWorkspaceBuildFlagsByID(
dbauthz.AsSystemRestricted(context.Background()),
database.UpdateWorkspaceBuildFlagsByIDParams{
ID: build.Build.ID,
HasAITask: sql.NullBool{Bool: true, Valid: true},
HasExternalAgent: sql.NullBool{Bool: false, Valid: false},
SidebarAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
UpdatedAt: build.Build.UpdatedAt,
},
)
require.NoError(t, err)
// Create a task record in the tasks table for the new data model.
task := dbgen.Task(t, db, database.TaskTable{
OrganizationID: orgID,
OwnerID: ownerID,
Name: build.Workspace.Name,
WorkspaceID: uuid.NullUUID{UUID: build.Workspace.ID, Valid: true},
TemplateVersionID: tv.TemplateVersion.ID,
TemplateParameters: []byte("{}"),
Prompt: prompt,
CreatedAt: dbtime.Now(),
})
// Link the task to the workspace app.
dbgen.TaskWorkspaceApp(t, db, database.TaskWorkspaceApp{
TaskID: task.ID,
WorkspaceBuildNumber: build.Build.BuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: agentID, Valid: true},
WorkspaceAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
})
return task
return build.Task
}
func TestExpTaskList(t *testing.T) {
+30 -97
View File
@@ -36,17 +36,9 @@ 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":
if r.URL.Query().Get("q") == "owner:\"me\"" {
httpapi.Write(ctx, w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
}{
Tasks: []codersdk.Task{},
Count: 0,
})
return
}
case "/api/experimental/tasks/me/doesnotexist":
httpapi.ResourceNotFound(w)
return
default:
t.Errorf("unexpected path: %s", r.URL.Path)
}
@@ -60,35 +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":
if r.URL.Query().Get("q") == "owner:\"me\"" {
httpapi.Write(ctx, w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
}{
Tasks: []codersdk.Task{{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
OwnerName: "me",
WorkspaceStatus: codersdk.WorkspaceStatusRunning,
CreatedAt: now,
UpdatedAt: now,
CurrentState: &codersdk.TaskStateEntry{
State: codersdk.TaskStateWorking,
Timestamp: now,
Message: "Thinking furiously...",
},
WorkspaceAgentHealth: &codersdk.WorkspaceAgentHealth{
Healthy: true,
},
WorkspaceAgentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleReady),
Status: codersdk.TaskStatusActive,
}},
Count: 1,
})
return
}
case "/api/experimental/tasks/me/11111111-1111-1111-1111-111111111111":
case "/api/experimental/tasks/me/exists":
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
WorkspaceStatus: codersdk.WorkspaceStatusRunning,
@@ -124,30 +88,21 @@ 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":
if r.URL.Query().Get("q") == "owner:\"me\"" {
// Return initial task state for --watch test
httpapi.Write(ctx, w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
}{
Tasks: []codersdk.Task{{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
OwnerName: "me",
WorkspaceStatus: codersdk.WorkspaceStatusPending,
CreatedAt: now.Add(-5 * time.Second),
UpdatedAt: now.Add(-5 * time.Second),
WorkspaceAgentHealth: &codersdk.WorkspaceAgentHealth{
Healthy: true,
},
WorkspaceAgentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleReady),
Status: codersdk.TaskStatusPending,
}},
Count: 1,
})
return
}
case "/api/experimental/tasks/me/exists":
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
OwnerName: "me",
WorkspaceStatus: codersdk.WorkspaceStatusPending,
CreatedAt: now.Add(-5 * time.Second),
UpdatedAt: now.Add(-5 * time.Second),
WorkspaceAgentHealth: &codersdk.WorkspaceAgentHealth{
Healthy: true,
},
WorkspaceAgentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleReady),
Status: codersdk.TaskStatusPending,
})
return
case "/api/experimental/tasks/me/11111111-1111-1111-1111-111111111111":
defer calls.Add(1)
switch calls.Load() {
@@ -263,40 +218,18 @@ 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":
if r.URL.Query().Get("q") == "owner:\"me\"" {
httpapi.Write(ctx, w, http.StatusOK, struct {
Tasks []codersdk.Task `json:"tasks"`
Count int `json:"count"`
}{
Tasks: []codersdk.Task{{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
OwnerName: "me",
WorkspaceStatus: codersdk.WorkspaceStatusRunning,
CreatedAt: ts,
UpdatedAt: ts,
CurrentState: &codersdk.TaskStateEntry{
State: codersdk.TaskStateWorking,
Timestamp: ts.Add(time.Second),
Message: "Thinking furiously...",
},
WorkspaceAgentHealth: &codersdk.WorkspaceAgentHealth{
Healthy: true,
},
WorkspaceAgentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleReady),
Status: codersdk.TaskStatusActive,
}},
Count: 1,
})
return
}
case "/api/experimental/tasks/me/11111111-1111-1111-1111-111111111111":
case "/api/experimental/tasks/me/exists":
httpapi.Write(ctx, w, http.StatusOK, codersdk.Task{
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
WorkspaceStatus: codersdk.WorkspaceStatusRunning,
CreatedAt: ts,
UpdatedAt: ts,
ID: uuid.MustParse("11111111-1111-1111-1111-111111111111"),
Name: "exists",
OwnerName: "me",
WorkspaceAgentHealth: &codersdk.WorkspaceAgentHealth{
Healthy: true,
},
WorkspaceAgentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleReady),
WorkspaceStatus: codersdk.WorkspaceStatusRunning,
CreatedAt: ts,
UpdatedAt: ts,
CurrentState: &codersdk.TaskStateEntry{
State: codersdk.TaskStateWorking,
Timestamp: ts.Add(time.Second),
+10 -15
View File
@@ -53,7 +53,6 @@ func Test_Tasks(t *testing.T) {
taskName = strings.ReplaceAll(testutil.GetRandomName(t), "_", "-")
)
//nolint:paralleltest // The sub-tests of this test must be run sequentially.
for _, tc := range []struct {
name string
cmdArgs []string
@@ -135,16 +134,15 @@ func Test_Tasks(t *testing.T) {
},
},
} {
t.Run(tc.name, func(t *testing.T) {
var stdout strings.Builder
inv, root := clitest.New(t, tc.cmdArgs...)
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
require.NoError(t, inv.WithContext(ctx).Run())
if tc.assertFn != nil {
tc.assertFn(stdout.String(), userClient)
}
})
t.Logf("test case: %q", tc.name)
var stdout strings.Builder
inv, root := clitest.New(t, tc.cmdArgs...)
inv.Stdout = &stdout
clitest.SetupConfig(t, userClient, root)
require.NoError(t, inv.WithContext(ctx).Run(), tc.name)
if tc.assertFn != nil {
tc.assertFn(stdout.String(), userClient)
}
}
}
@@ -293,7 +291,6 @@ func createAITaskTemplate(t *testing.T, client *codersdk.Client, orgID uuid.UUID
{
Type: &proto.Response_Plan{
Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
},
},
@@ -328,9 +325,7 @@ func createAITaskTemplate(t *testing.T, client *codersdk.Client, orgID uuid.UUID
},
AiTasks: []*proto.AITask{
{
SidebarApp: &proto.AITaskSidebarApp{
Id: taskAppID.String(),
},
AppId: taskAppID.String(),
},
},
},
+355
View File
@@ -0,0 +1,355 @@
package cli_test
import (
"bytes"
"net/url"
"os"
"path"
"runtime"
"testing"
"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/coderd/coderdtest"
"github.com/coder/coder/v2/pty/ptytest"
)
// 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
}
return cred, nil
}
func (m *mockKeyring) Write(_ *url.URL, token string) error {
m.credentials[mockServiceName] = token
return nil
}
func (m *mockKeyring) Delete(_ *url.URL) error {
_, ok := m.credentials[mockServiceName]
if !ok {
return os.ErrNotExist
}
delete(m.credentials, mockServiceName)
return nil
}
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.
t.Parallel()
t.Run("Login", func(t *testing.T) {
t.Parallel()
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Create a pty for interactive prompts
pty := ptytest.New(t)
// Create CLI invocation with --use-keyring flag
inv, cfg := clitest.New(t,
"login",
"--force-tty",
"--use-keyring",
"--no-open",
client.URL.String(),
)
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() {
defer close(doneChan)
err := inv.Run()
assert.NoError(t, err)
}()
// Provide the token when prompted
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Verify that session file was NOT created (using keyring instead)
sessionFile := path.Join(string(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")
require.Equal(t, client.SessionToken(), cred, "stored token should match login token")
})
t.Run("Logout", func(t *testing.T) {
t.Parallel()
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Create a pty for interactive prompts
pty := ptytest.New(t)
// First, login with --use-keyring
loginInv, cfg := clitest.New(t,
"login",
"--force-tty",
"--use-keyring",
"--no-open",
client.URL.String(),
)
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)
err := loginInv.Run()
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Verify credential exists in mock keyring
cred, err := mockBackend.Read(nil)
require.NoError(t, err, "read credential should succeed before logout")
require.NotEmpty(t, cred, "credential should exist after logout")
// Now run logout with --use-keyring
logoutInv, _ := clitest.New(t,
"logout",
"--use-keyring",
"--yes",
"--global-config", string(cfg),
)
// Inject the same mock backend
var logoutRoot cli.RootCmd
logoutCmd, err := logoutRoot.Command(logoutRoot.AGPL())
require.NoError(t, err)
logoutRoot.WithSessionStorageBackend(mockBackend)
logoutInv.Command = logoutCmd
var logoutOut bytes.Buffer
logoutInv.Stdout = &logoutOut
err = logoutInv.Run()
require.NoError(t, err, "logout should succeed")
// Verify the credential was deleted from mock keyring
_, err = mockBackend.Read(nil)
require.ErrorIs(t, err, os.ErrNotExist, "credential should be deleted from keyring after logout")
})
t.Run("OmitFlag", func(t *testing.T) {
t.Parallel()
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// Create a pty for interactive prompts
pty := ptytest.New(t)
// --use-keyring flag omitted (should use file-based storage)
inv, cfg := clitest.New(t,
"login",
"--force-tty",
"--no-open",
client.URL.String(),
)
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(cfg), "session")
_, err := os.Stat(sessionFile)
require.NoError(t, err, "session file should exist when NOT using --use-keyring")
// 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("EnvironmentVariable", func(t *testing.T) {
t.Parallel()
// Create a test server
client := coderdtest.New(t, nil)
coderdtest.CreateFirstUser(t, client)
// 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",
"--force-tty",
"--no-open",
client.URL.String(),
)
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
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 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 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)
})
}
func TestUseKeyringUnsupportedOS(t *testing.T) {
// Verify that trying to use --use-keyring on an unsupported operating system produces
// a helpful error message.
t.Parallel()
// Only run this on an unsupported OS.
if runtime.GOOS == "windows" || runtime.GOOS == "darwin" {
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.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,
"login",
"--force-tty",
"--no-open",
client.URL.String(),
)
loginInv.Stdin = pty.Input()
loginInv.Stdout = pty.Output()
doneChan := make(chan struct{})
go func() {
defer close(doneChan)
err := loginInv.Run()
assert.NoError(t, err)
}()
pty.ExpectMatch("Paste your token here:")
pty.WriteLine(client.SessionToken())
pty.ExpectMatch("Welcome to Coder")
<-doneChan
// Now try to logout with --use-keyring on an unsupported OS
logoutInv, _ := clitest.New(t,
"logout",
"--use-keyring",
"--yes",
"--global-config", string(cfg),
)
err := logoutInv.Run()
// Verify we got an error about unsupported OS
require.Error(t, err)
require.Contains(t, err.Error(), expMessage)
})
}
+24 -5
View File
@@ -19,6 +19,7 @@ import (
"github.com/coder/pretty"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/sessionstore"
"github.com/coder/coder/v2/coderd/userpassword"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/serpent"
@@ -114,9 +115,11 @@ func (r *RootCmd) loginWithPassword(
}
sessionToken := resp.SessionToken
config := r.createConfig()
err = config.Session().Write(sessionToken)
err = r.ensureTokenBackend().Write(client.URL, sessionToken)
if err != nil {
if xerrors.Is(err, sessionstore.ErrNotImplemented) {
return errKeyringNotSupported
}
return xerrors.Errorf("write session token: %w", err)
}
@@ -149,11 +152,15 @@ func (r *RootCmd) login() *serpent.Command {
useTokenForSession bool
)
cmd := &serpent.Command{
Use: "login [<url>]",
Short: "Authenticate with Coder deployment",
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.",
Middleware: serpent.RequireRangeArgs(0, 1),
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()
rawURL := ""
var urlSource string
@@ -198,6 +205,15 @@ func (r *RootCmd) login() *serpent.Command {
return err
}
// Check keyring availability before prompting the user for a token to fail fast.
if r.useKeyring {
backend := r.ensureTokenBackend()
_, err := backend.Read(client.URL)
if err != nil && xerrors.Is(err, sessionstore.ErrNotImplemented) {
return errKeyringNotSupported
}
}
hasFirstUser, err := client.HasFirstUser(ctx)
if err != nil {
return xerrors.Errorf("Failed to check server %q for first user, is the URL correct and is coder accessible from your browser? Error - has initial user: %w", serverURL.String(), err)
@@ -394,8 +410,11 @@ func (r *RootCmd) login() *serpent.Command {
}
config := r.createConfig()
err = config.Session().Write(sessionToken)
err = r.ensureTokenBackend().Write(client.URL, sessionToken)
if err != nil {
if xerrors.Is(err, sessionstore.ErrNotImplemented) {
return errKeyringNotSupported
}
return xerrors.Errorf("write session token: %w", err)
}
err = config.URL().Write(serverURL.String())
+8 -3
View File
@@ -8,6 +8,7 @@ import (
"golang.org/x/xerrors"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/sessionstore"
"github.com/coder/serpent"
)
@@ -46,11 +47,15 @@ func (r *RootCmd) logout() *serpent.Command {
errors = append(errors, xerrors.Errorf("remove URL file: %w", err))
}
err = config.Session().Delete()
err = r.ensureTokenBackend().Delete(client.URL)
// Only throw error if the session configuration file is present,
// otherwise the user is already logged out, and we proceed
if err != nil && !os.IsNotExist(err) {
errors = append(errors, xerrors.Errorf("remove session file: %w", err))
if err != nil && !xerrors.Is(err, os.ErrNotExist) {
if xerrors.Is(err, sessionstore.ErrNotImplemented) {
errors = append(errors, errKeyringNotSupported)
} else {
errors = append(errors, xerrors.Errorf("remove session token: %w", err))
}
}
err = config.Organization().Delete()
+72 -8
View File
@@ -37,6 +37,7 @@ import (
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/cli/gitauth"
"github.com/coder/coder/v2/cli/sessionstore"
"github.com/coder/coder/v2/cli/telemetry"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/codersdk/agentsdk"
@@ -54,6 +55,8 @@ var (
// ErrSilent is a sentinel error that tells the command handler to just exit with a non-zero error, but not print
// 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")
)
const (
@@ -68,12 +71,14 @@ const (
varVerbose = "verbose"
varDisableDirect = "disable-direct-connections"
varDisableNetworkTelemetry = "disable-network-telemetry"
varUseKeyring = "use-keyring"
notLoggedInMessage = "You are not logged in. Try logging in using '%s login <url>'."
envNoVersionCheck = "CODER_NO_VERSION_WARNING"
envNoFeatureWarning = "CODER_NO_FEATURE_WARNING"
envSessionToken = "CODER_SESSION_TOKEN"
envUseKeyring = "CODER_USE_KEYRING"
//nolint:gosec
envAgentToken = "CODER_AGENT_TOKEN"
//nolint:gosec
@@ -474,6 +479,15 @@ func (r *RootCmd) Command(subcommands []*serpent.Command) (*serpent.Command, err
Value: serpent.BoolOf(&r.disableNetworkTelemetry),
Group: globalGroup,
},
{
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,
},
{
Flag: "debug-http",
Description: "Debug codersdk HTTP requests.",
@@ -508,6 +522,7 @@ func (r *RootCmd) Command(subcommands []*serpent.Command) (*serpent.Command, err
type RootCmd struct {
clientURL *url.URL
token string
tokenBackend sessionstore.Backend
globalConfig string
header []string
headerCommand string
@@ -522,6 +537,24 @@ type RootCmd struct {
disableNetworkTelemetry bool
noVersionCheck bool
noFeatureWarning bool
useKeyring bool
// TestOverrideSDKClient is returned by GetClient if set. This is used in unit testing to mock or fake the
// *codersdk.Client
TestOverrideSDKClient any
}
// GetClient gets the SDK client of the given type. In tests, this can be used with TestOverrideSDKClient to mock or
// fake the client. In production, this returns a *codersdk.Client.
func GetClient[T any](r *RootCmd, inv *serpent.Invocation) (T, error) {
if r.TestOverrideSDKClient != nil {
// nolint: forcetypeassert
return r.TestOverrideSDKClient.(T), nil
}
var a any
a, err := r.InitClient(inv)
// nolint: forcetypeassert
return a.(T), err
}
// InitClient creates and configures a new client with authentication, telemetry,
@@ -549,14 +582,19 @@ func (r *RootCmd) InitClient(inv *serpent.Invocation) (*codersdk.Client, error)
return nil, err
}
}
// Read the token stored on disk.
if r.token == "" {
r.token, err = conf.Session().Read()
tok, err := r.ensureTokenBackend().Read(r.clientURL)
// Even if there isn't a token, we don't care.
// Some API routes can be unauthenticated.
if err != nil && !os.IsNotExist(err) {
if err != nil && !xerrors.Is(err, os.ErrNotExist) {
if xerrors.Is(err, sessionstore.ErrNotImplemented) {
return nil, errKeyringNotSupported
}
return nil, err
}
if tok != "" {
r.token = tok
}
}
// Configure HTTP client with transport wrappers
@@ -588,7 +626,6 @@ func (r *RootCmd) InitClient(inv *serpent.Invocation) (*codersdk.Client, error)
// This allows commands to run without requiring authentication, but still use auth if available.
func (r *RootCmd) TryInitClient(inv *serpent.Invocation) (*codersdk.Client, error) {
conf := r.createConfig()
var err error
// Read the client URL stored on disk.
if r.clientURL == nil || r.clientURL.String() == "" {
rawURL, err := conf.URL().Read()
@@ -605,14 +642,19 @@ func (r *RootCmd) TryInitClient(inv *serpent.Invocation) (*codersdk.Client, erro
}
}
}
// Read the token stored on disk.
if r.token == "" {
r.token, err = conf.Session().Read()
tok, err := r.ensureTokenBackend().Read(r.clientURL)
// Even if there isn't a token, we don't care.
// Some API routes can be unauthenticated.
if err != nil && !os.IsNotExist(err) {
if err != nil && !xerrors.Is(err, os.ErrNotExist) {
if xerrors.Is(err, sessionstore.ErrNotImplemented) {
return nil, errKeyringNotSupported
}
return nil, err
}
if tok != "" {
r.token = tok
}
}
// Only configure the client if we have a URL
@@ -688,6 +730,24 @@ func (r *RootCmd) createUnauthenticatedClient(ctx context.Context, serverURL *ur
return client, nil
}
// ensureTokenBackend returns the session token storage backend, creating it if necessary.
// This must be called after flags are parsed so we can respect the value of the --use-keyring
// flag.
func (r *RootCmd) ensureTokenBackend() sessionstore.Backend {
if r.tokenBackend == nil {
if r.useKeyring {
r.tokenBackend = sessionstore.NewKeyring()
} else {
r.tokenBackend = sessionstore.NewFile(r.createConfig)
}
}
return r.tokenBackend
}
func (r *RootCmd) WithSessionStorageBackend(backend sessionstore.Backend) {
r.tokenBackend = backend
}
type AgentAuth struct {
// Agent Client config
agentToken string
@@ -850,10 +910,14 @@ func splitNamedWorkspace(identifier string) (owner string, workspaceName string,
return owner, workspaceName, nil
}
type workspaceGetterByName interface {
WorkspaceByOwnerAndName(context.Context, string, string, codersdk.WorkspaceOptions) (codersdk.Workspace, error)
}
// namedWorkspace fetches and returns a workspace by an identifier, which may be either
// a bare name (for a workspace owned by the current user) or a "user/workspace" combination,
// where user is either a username or UUID.
func namedWorkspace(ctx context.Context, client *codersdk.Client, identifier string) (codersdk.Workspace, error) {
func namedWorkspace(ctx context.Context, client workspaceGetterByName, identifier string) (codersdk.Workspace, error) {
owner, name, err := splitNamedWorkspace(identifier)
if err != nil {
return codersdk.Workspace{}, err
+1
View File
@@ -1476,6 +1476,7 @@ func newProvisionerDaemon(
Listener: terraformServer,
Logger: provisionerLogger,
WorkDirectory: workDir,
Experiments: coderAPI.Experiments,
},
CachePath: tfDir,
Tracer: tracer,
+245
View File
@@ -0,0 +1,245 @@
// Package sessionstore provides CLI session token storage mechanisms.
// Operating system keyring storage is intended to have compatibility with other Coder
// applications (e.g. Coder Desktop, Coder provider for JetBrains Toolbox, etc) so that
// applications can read/write the same credential stored in the keyring.
//
// Note that we aren't using an existing Go package zalando/go-keyring here for a few
// reasons. 1) It prescribes the format of the target credential name in the OS keyrings,
// which makes our life difficult for compatibility with other Coder applications. 2)
// It uses init functions that make it difficult to test with. As a result, the OS
// keyring implementations may be adapted from zalando/go-keyring source (i.e. Windows).
package sessionstore
import (
"encoding/json"
"errors"
"net/url"
"os"
"strings"
"golang.org/x/xerrors"
"github.com/coder/coder/v2/cli/config"
)
// Backend is a storage backend for session tokens.
type Backend interface {
// Read returns the session token for the given server URL or an error, if any. It
// will return os.ErrNotExist if no token exists for the given URL.
Read(serverURL *url.URL) (string, error)
// Write stores the session token for the given server URL.
Write(serverURL *url.URL, token string) error
// Delete removes the session token for the given server URL or an error, if any.
// It will return os.ErrNotExist error if no token exists to delete.
Delete(serverURL *url.URL) error
}
var (
// ErrSetDataTooBig is returned if `keyringProvider.Set` was called with too much data.
// On macOS: The combination of service, username & password should not exceed ~3000 bytes
// On Windows: The service is limited to 32KiB while the password is limited to 2560 bytes
ErrSetDataTooBig = xerrors.New("data passed to Set was too big")
// ErrNotImplemented represents when keyring usage is not implemented on the current
// operating system.
ErrNotImplemented = xerrors.New("not implemented")
)
const (
// defaultServiceName is the service name used in keyrings for storing Coder CLI session
// tokens.
defaultServiceName = "coder-v2-credentials"
)
// keyringProvider represents an operating system keyring. The expectation
// is these methods operate on the user/login keyring.
type keyringProvider interface {
// Set stores the given credential for a service name in the operating system
// keyring.
Set(service, credential string) error
// Get retrieves the credential from the keyring. It must return os.ErrNotExist
// if the credential is not found.
Get(service string) ([]byte, error)
// Delete deletes the credential from the keyring. It must return os.ErrNotExist
// if the credential is not found.
Delete(service string) error
}
// credential represents a single credential entry.
type credential struct {
CoderURL string `json:"coder_url"`
APIToken string `json:"api_token"`
}
// credentialsMap represents the JSON structure stored in the operating system keyring.
// It supports storing multiple credentials for different server URLs.
type credentialsMap map[string]credential
// normalizeHost returns a normalized version of the URL host for use as a map key.
func normalizeHost(u *url.URL) (string, error) {
if u == nil || u.Host == "" {
return "", xerrors.New("nil server URL")
}
return strings.TrimSpace(strings.ToLower(u.Host)), nil
}
// parseCredentialsJSON parses the JSON from the keyring into a credentialsMap.
func parseCredentialsJSON(jsonData []byte) (credentialsMap, error) {
if len(jsonData) == 0 {
return make(credentialsMap), nil
}
var creds credentialsMap
if err := json.Unmarshal(jsonData, &creds); err != nil {
return nil, xerrors.Errorf("unmarshal credentials: %w", err)
}
return creds, nil
}
// Keyring is a Backend that exclusively stores the session token in the operating
// system keyring. Happy path usage of this type should start with NewKeyring.
// It stores a JSON object in the keyring that supports multiple credentials for
// different server URLs, providing compatibility with Coder Desktop and other Coder
// applications.
type Keyring struct {
provider keyringProvider
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.
func NewKeyringWithService(serviceName string) Keyring {
return Keyring{
provider: operatingSystemKeyring{},
serviceName: serviceName,
}
}
func (o Keyring) Read(serverURL *url.URL) (string, error) {
host, err := normalizeHost(serverURL)
if err != nil {
return "", err
}
credJSON, err := o.provider.Get(o.serviceName)
if err != nil {
return "", err
}
if len(credJSON) == 0 {
return "", os.ErrNotExist
}
creds, err := parseCredentialsJSON(credJSON)
if err != nil {
return "", xerrors.Errorf("read: parse existing credentials: %w", err)
}
// Return the credential for the specified URL
cred, ok := creds[host]
if !ok {
return "", os.ErrNotExist
}
return cred.APIToken, nil
}
func (o Keyring) Write(serverURL *url.URL, token string) error {
host, err := normalizeHost(serverURL)
if err != nil {
return err
}
existingJSON, err := o.provider.Get(o.serviceName)
if err != nil && !errors.Is(err, os.ErrNotExist) {
return xerrors.Errorf("read existing credentials: %w", err)
}
creds, err := parseCredentialsJSON(existingJSON)
if err != nil {
return xerrors.Errorf("write: parse existing credentials: %w", err)
}
// Upsert the credential for this URL.
creds[host] = credential{
CoderURL: host,
APIToken: token,
}
credsJSON, err := json.Marshal(creds)
if err != nil {
return xerrors.Errorf("marshal credentials: %w", err)
}
err = o.provider.Set(o.serviceName, string(credsJSON))
if err != nil {
return xerrors.Errorf("write credentials to keyring: %w", err)
}
return nil
}
func (o Keyring) Delete(serverURL *url.URL) error {
host, err := normalizeHost(serverURL)
if err != nil {
return err
}
existingJSON, err := o.provider.Get(o.serviceName)
if err != nil {
return err
}
creds, err := parseCredentialsJSON(existingJSON)
if err != nil {
return xerrors.Errorf("failed to parse existing credentials: %w", err)
}
if _, ok := creds[host]; !ok {
return os.ErrNotExist
}
delete(creds, host)
// Delete the entire keyring entry when no credentials remain.
if len(creds) == 0 {
return o.provider.Delete(o.serviceName)
}
// Write back the updated credentials map.
credsJSON, err := json.Marshal(creds)
if err != nil {
return xerrors.Errorf("failed to marshal credentials: %w", err)
}
return o.provider.Set(o.serviceName, string(credsJSON))
}
// File is a Backend that exclusively stores the session token in a file on disk.
type File struct {
config func() config.Root
}
func NewFile(f func() config.Root) *File {
return &File{config: f}
}
func (f *File) Read(_ *url.URL) (string, error) {
return f.config().Session().Read()
}
func (f *File) Write(_ *url.URL, token string) error {
return f.config().Session().Write(token)
}
func (f *File) Delete(_ *url.URL) error {
return f.config().Session().Delete()
}
+105
View File
@@ -0,0 +1,105 @@
//go:build darwin
package sessionstore
import (
"encoding/base64"
"fmt"
"io"
"os"
"os/exec"
"regexp"
"strings"
)
const (
// fixedUsername is the fixed username used for all keychain entries.
// Since our interface only uses service names, we use a constant username.
fixedUsername = "coder-login-credentials"
execPathKeychain = "/usr/bin/security"
notFoundStr = "could not be found"
)
// operatingSystemKeyring implements keyringProvider for macOS.
// It is largely adapted from the zalando/go-keyring package.
type operatingSystemKeyring struct{}
func (operatingSystemKeyring) Set(service, credential string) error {
// if the added secret has multiple lines or some non ascii,
// macOS will hex encode it on return. To avoid getting garbage, we
// encode all passwords
password := base64.StdEncoding.EncodeToString([]byte(credential))
cmd := exec.Command(execPathKeychain, "-i")
stdIn, err := cmd.StdinPipe()
if err != nil {
return err
}
if err = cmd.Start(); err != nil {
return err
}
command := fmt.Sprintf("add-generic-password -U -s %s -a %s -w %s\n",
shellEscape(service),
shellEscape(fixedUsername),
shellEscape(password))
if len(command) > 4096 {
return ErrSetDataTooBig
}
if _, err := io.WriteString(stdIn, command); err != nil {
return err
}
if err = stdIn.Close(); err != nil {
return err
}
return cmd.Wait()
}
func (operatingSystemKeyring) Get(service string) ([]byte, error) {
out, err := exec.Command(
execPathKeychain,
"find-generic-password",
"-s", service,
"-wa", fixedUsername).CombinedOutput()
if err != nil {
if strings.Contains(string(out), notFoundStr) {
return nil, os.ErrNotExist
}
return nil, err
}
trimStr := strings.TrimSpace(string(out))
return base64.StdEncoding.DecodeString(trimStr)
}
func (operatingSystemKeyring) Delete(service string) error {
out, err := exec.Command(
execPathKeychain,
"delete-generic-password",
"-s", service,
"-a", fixedUsername).CombinedOutput()
if strings.Contains(string(out), notFoundStr) {
return os.ErrNotExist
}
return err
}
// shellEscape returns a shell-escaped version of the string s.
// This is adapted from github.com/zalando/go-keyring/internal/shellescape.
func shellEscape(s string) string {
if len(s) == 0 {
return "''"
}
pattern := regexp.MustCompile(`[^\w@%+=:,./-]`)
if pattern.MatchString(s) {
return "'" + strings.ReplaceAll(s, "'", "'\"'\"'") + "'"
}
return s
}
@@ -0,0 +1,34 @@
//go:build darwin
package sessionstore_test
import (
"encoding/base64"
"os/exec"
"testing"
)
const (
execPathKeychain = "/usr/bin/security"
fixedUsername = "coder-login-credentials"
)
func readRawKeychainCredential(t *testing.T, service string) []byte {
t.Helper()
out, err := exec.Command(
execPathKeychain,
"find-generic-password",
"-s", service,
"-wa", fixedUsername).CombinedOutput()
if err != nil {
t.Fatal(err)
}
dst := make([]byte, base64.StdEncoding.DecodedLen(len(out)))
n, err := base64.StdEncoding.Decode(dst, out)
if err != nil {
t.Fatal(err)
}
return dst[:n]
}
@@ -0,0 +1,121 @@
package sessionstore
import (
"encoding/json"
"net/url"
"testing"
"github.com/stretchr/testify/require"
)
func TestNormalizeHost(t *testing.T) {
t.Parallel()
tests := []struct {
name string
url *url.URL
want string
wantErr bool
}{
{
name: "StandardHost",
url: &url.URL{Host: "coder.example.com"},
want: "coder.example.com",
},
{
name: "HostWithPort",
url: &url.URL{Host: "coder.example.com:8080"},
want: "coder.example.com:8080",
},
{
name: "UppercaseHost",
url: &url.URL{Host: "CODER.EXAMPLE.COM"},
want: "coder.example.com",
},
{
name: "HostWithWhitespace",
url: &url.URL{Host: " coder.example.com "},
want: "coder.example.com",
},
{
name: "NilURL",
url: nil,
want: "",
wantErr: true,
},
{
name: "EmptyHost",
url: &url.URL{Host: ""},
want: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got, err := normalizeHost(tt.url)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, tt.want, got)
})
}
}
func TestParseCredentialsJSON(t *testing.T) {
t.Parallel()
t.Run("Empty", func(t *testing.T) {
t.Parallel()
creds, err := parseCredentialsJSON(nil)
require.NoError(t, err)
require.NotNil(t, creds)
require.Empty(t, creds)
})
t.Run("NewFormat", func(t *testing.T) {
t.Parallel()
jsonData := []byte(`{
"coder1.example.com": {"coder_url": "coder1.example.com", "api_token": "token1"},
"coder2.example.com": {"coder_url": "coder2.example.com", "api_token": "token2"}
}`)
creds, err := parseCredentialsJSON(jsonData)
require.NoError(t, err)
require.Len(t, creds, 2)
require.Equal(t, "token1", creds["coder1.example.com"].APIToken)
require.Equal(t, "token2", creds["coder2.example.com"].APIToken)
})
t.Run("InvalidJSON", func(t *testing.T) {
t.Parallel()
jsonData := []byte(`{invalid json}`)
_, err := parseCredentialsJSON(jsonData)
require.Error(t, err)
})
}
func TestCredentialsMap_RoundTrip(t *testing.T) {
t.Parallel()
creds := credentialsMap{
"coder1.example.com": {
CoderURL: "coder1.example.com",
APIToken: "token1",
},
"coder2.example.com:8080": {
CoderURL: "coder2.example.com:8080",
APIToken: "token2",
},
}
jsonData, err := json.Marshal(creds)
require.NoError(t, err)
parsed, err := parseCredentialsJSON(jsonData)
require.NoError(t, err)
require.Equal(t, creds, parsed)
}
+17
View File
@@ -0,0 +1,17 @@
//go:build !windows && !darwin
package sessionstore
type operatingSystemKeyring struct{}
func (operatingSystemKeyring) Set(_, _ string) error {
return ErrNotImplemented
}
func (operatingSystemKeyring) Get(_ string) ([]byte, error) {
return nil, ErrNotImplemented
}
func (operatingSystemKeyring) Delete(_ string) error {
return ErrNotImplemented
}
@@ -0,0 +1,10 @@
//go:build !windows && !darwin
package sessionstore_test
import "testing"
func readRawKeychainCredential(t *testing.T, _ string) []byte {
t.Fatal("not implemented")
return nil
}
+408
View File
@@ -0,0 +1,408 @@
package sessionstore_test
import (
"encoding/json"
"errors"
"fmt"
"net/url"
"os"
"path"
"runtime"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/config"
"github.com/coder/coder/v2/cli/sessionstore"
)
type storedCredentials map[string]struct {
CoderURL string `json:"coder_url"`
APIToken string `json:"api_token"`
}
// Generate a test service name for use with the OS keyring. It uses a combination
// of the test name and a nanosecond timestamp to prevent collisions.
func keyringTestServiceName(t *testing.T) string {
t.Helper()
return t.Name() + "_" + fmt.Sprintf("%v", time.Now().UnixNano())
}
func TestKeyring(t *testing.T) {
t.Parallel()
if runtime.GOOS != "windows" && runtime.GOOS != "darwin" {
t.Skip("linux is not supported yet")
}
// This test exercises use of the operating system keyring. As a result,
// the operating system keyring is expected to be available.
const (
testURL = "http://127.0.0.1:1337"
testURL2 = "http://127.0.0.1:1338"
)
t.Run("ReadNonExistent", func(t *testing.T) {
t.Parallel()
backend := sessionstore.NewKeyringWithService(keyringTestServiceName(t))
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
t.Cleanup(func() { _ = backend.Delete(srvURL) })
_, err = backend.Read(srvURL)
require.Error(t, err)
require.True(t, os.IsNotExist(err), "expected os.ErrNotExist when reading non-existent token")
})
t.Run("DeleteNonExistent", func(t *testing.T) {
t.Parallel()
backend := sessionstore.NewKeyringWithService(keyringTestServiceName(t))
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
t.Cleanup(func() { _ = backend.Delete(srvURL) })
err = backend.Delete(srvURL)
require.Error(t, err)
require.True(t, errors.Is(err, os.ErrNotExist), "expected os.ErrNotExist when deleting non-existent token")
})
t.Run("WriteAndRead", func(t *testing.T) {
t.Parallel()
backend := sessionstore.NewKeyringWithService(keyringTestServiceName(t))
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
t.Cleanup(func() { _ = backend.Delete(srvURL) })
dir := t.TempDir()
expSessionFile := path.Join(dir, "session")
const inputToken = "test-keyring-token-12345"
err = backend.Write(srvURL, inputToken)
require.NoError(t, err)
// Verify no session file was created (keyring stores in OS keyring, not file)
_, err = os.Stat(expSessionFile)
require.True(t, errors.Is(err, os.ErrNotExist), "expected session token file to not exist when using keyring")
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, inputToken, token)
// Clean up
err = backend.Delete(srvURL)
require.NoError(t, err)
})
t.Run("WriteAndDelete", func(t *testing.T) {
t.Parallel()
backend := sessionstore.NewKeyringWithService(keyringTestServiceName(t))
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
t.Cleanup(func() { _ = backend.Delete(srvURL) })
const inputToken = "test-keyring-token-67890"
err = backend.Write(srvURL, inputToken)
require.NoError(t, err)
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, inputToken, token)
err = backend.Delete(srvURL)
require.NoError(t, err)
_, err = backend.Read(srvURL)
require.Error(t, err)
require.True(t, os.IsNotExist(err), "expected os.ErrNotExist after deleting token")
})
t.Run("OverwriteToken", func(t *testing.T) {
t.Parallel()
backend := sessionstore.NewKeyringWithService(keyringTestServiceName(t))
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
t.Cleanup(func() { _ = backend.Delete(srvURL) })
// Write first token
const firstToken = "first-keyring-token"
err = backend.Write(srvURL, firstToken)
require.NoError(t, err)
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, firstToken, token)
// Overwrite with second token
const secondToken = "second-keyring-token"
err = backend.Write(srvURL, secondToken)
require.NoError(t, err)
token, err = backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, secondToken, token)
// Clean up
err = backend.Delete(srvURL)
require.NoError(t, err)
})
t.Run("MultipleServers", func(t *testing.T) {
t.Parallel()
backend := sessionstore.NewKeyringWithService(keyringTestServiceName(t))
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
srvURL2, err := url.Parse(testURL2)
require.NoError(t, err)
t.Cleanup(func() {
_ = backend.Delete(srvURL)
_ = backend.Delete(srvURL2)
})
// Write token for server 1
const token1 = "token-for-server-1"
err = backend.Write(srvURL, token1)
require.NoError(t, err)
// Write token for server 2 (should NOT overwrite server 1)
const token2 = "token-for-server-2"
err = backend.Write(srvURL2, token2)
require.NoError(t, err)
// Read server 1's credential
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, token1, token)
// Read server 2's credential
token, err = backend.Read(srvURL2)
require.NoError(t, err)
require.Equal(t, token2, token)
// Delete server 1's credential
err = backend.Delete(srvURL)
require.NoError(t, err)
// Verify server 1's credential is gone
_, err = backend.Read(srvURL)
require.Error(t, err)
require.True(t, os.IsNotExist(err))
// Verify server 2's credential still exists
token, err = backend.Read(srvURL2)
require.NoError(t, err)
require.Equal(t, token2, token)
// Clean up remaining credentials
err = backend.Delete(srvURL2)
require.NoError(t, err)
})
t.Run("StorageFormat", func(t *testing.T) {
t.Parallel()
// The storage format must remain consistent to ensure we don't break
// compatibility with other Coder related applications that may read
// or decode the same credential.
const testURL1 = "http://127.0.0.1:1337"
srv1URL, err := url.Parse(testURL1)
require.NoError(t, err)
const testURL2 = "http://127.0.0.1:1338"
srv2URL, err := url.Parse(testURL2)
require.NoError(t, err)
serviceName := keyringTestServiceName(t)
backend := sessionstore.NewKeyringWithService(serviceName)
t.Cleanup(func() {
_ = backend.Delete(srv1URL)
_ = backend.Delete(srv2URL)
})
// Write token for server 1
const token1 = "token-server-1"
err = backend.Write(srv1URL, token1)
require.NoError(t, err)
// Write token for server 2 (should NOT overwrite server 1's token)
const token2 = "token-server-2"
err = backend.Write(srv2URL, token2)
require.NoError(t, err)
// Verify both credentials are stored in the raw format and can
// be extracted through the Backend API.
rawCredential := readRawKeychainCredential(t, serviceName)
storedCreds := make(storedCredentials)
err = json.Unmarshal(rawCredential, &storedCreds)
require.NoError(t, err, "unmarshalling stored credentials")
// Both credentials should exist
require.Len(t, storedCreds, 2)
require.Equal(t, token1, storedCreds[srv1URL.Host].APIToken)
require.Equal(t, token2, storedCreds[srv2URL.Host].APIToken)
// Read individual credentials
token, err := backend.Read(srv1URL)
require.NoError(t, err)
require.Equal(t, token1, token)
token, err = backend.Read(srv2URL)
require.NoError(t, err)
require.Equal(t, token2, token)
// Cleanup
err = backend.Delete(srv1URL)
require.NoError(t, err)
err = backend.Delete(srv2URL)
require.NoError(t, err)
})
}
func TestFile(t *testing.T) {
const (
testURL = "http://127.0.0.1:1337"
testURL2 = "http://127.0.0.1:1338"
)
t.Parallel()
t.Run("ReadNonExistent", func(t *testing.T) {
t.Parallel()
dir := t.TempDir()
backend := sessionstore.NewFile(func() config.Root { return config.Root(dir) })
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
_, err = backend.Read(srvURL)
require.Error(t, err)
require.True(t, os.IsNotExist(err))
})
t.Run("WriteAndRead", func(t *testing.T) {
t.Parallel()
dir := t.TempDir()
backend := sessionstore.NewFile(func() config.Root { return config.Root(dir) })
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
// Write a token
const inputToken = "test-token-12345"
err = backend.Write(srvURL, inputToken)
require.NoError(t, err)
// Verify the session file was created
sessionFile := config.Root(dir).Session()
require.True(t, sessionFile.Exists())
// Read the token back
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, inputToken, token)
})
t.Run("WriteAndDelete", func(t *testing.T) {
t.Parallel()
dir := t.TempDir()
backend := sessionstore.NewFile(func() config.Root { return config.Root(dir) })
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
// Write a token
const inputToken = "test-token-67890"
err = backend.Write(srvURL, inputToken)
require.NoError(t, err)
// Verify the token was written
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, inputToken, token)
// Delete the token
err = backend.Delete(srvURL)
require.NoError(t, err)
// Verify the token is gone
_, err = backend.Read(srvURL)
require.Error(t, err)
require.True(t, os.IsNotExist(err))
})
t.Run("DeleteNonExistent", func(t *testing.T) {
t.Parallel()
dir := t.TempDir()
backend := sessionstore.NewFile(func() config.Root { return config.Root(dir) })
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
// Attempt to delete a non-existent token
err = backend.Delete(srvURL)
require.Error(t, err)
require.True(t, os.IsNotExist(err))
})
t.Run("OverwriteToken", func(t *testing.T) {
t.Parallel()
dir := t.TempDir()
backend := sessionstore.NewFile(func() config.Root { return config.Root(dir) })
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
// Write first token
const firstToken = "first-token"
err = backend.Write(srvURL, firstToken)
require.NoError(t, err)
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, firstToken, token)
// Overwrite with second token
const secondToken = "second-token"
err = backend.Write(srvURL, secondToken)
require.NoError(t, err)
token, err = backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, secondToken, token)
})
t.Run("WriteIgnoresURL", func(t *testing.T) {
t.Parallel()
dir := t.TempDir()
backend := sessionstore.NewFile(func() config.Root { return config.Root(dir) })
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
srvURL2, err := url.Parse(testURL2)
require.NoError(t, err)
//nolint:gosec // Write with first URL test token
const firstToken = "token-for-url1"
err = backend.Write(srvURL, firstToken)
require.NoError(t, err)
//nolint:gosec // Write with second URL - should overwrite
const secondToken = "token-for-url2"
err = backend.Write(srvURL2, secondToken)
require.NoError(t, err)
// Should have the second token (File backend doesn't differentiate by URL)
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, secondToken, token)
})
}
+60
View File
@@ -0,0 +1,60 @@
//go:build windows
package sessionstore
import (
"errors"
"os"
"syscall"
"github.com/danieljoos/wincred"
)
// operatingSystemKeyring implements keyringProvider and uses Windows Credential Manager.
// It is largely adapted from the zalando/go-keyring package.
type operatingSystemKeyring struct{}
func (operatingSystemKeyring) Set(service, credential string) error {
// password may not exceed 2560 bytes (https://github.com/jaraco/keyring/issues/540#issuecomment-968329967)
if len(credential) > 2560 {
return ErrSetDataTooBig
}
// service may not exceed 512 bytes (might need more testing)
if len(service) >= 512 {
return ErrSetDataTooBig
}
// service may not exceed 32k but problems occur before that
// so we limit it to 30k
if len(service) > 1024*30 {
return ErrSetDataTooBig
}
cred := wincred.NewGenericCredential(service)
cred.CredentialBlob = []byte(credential)
cred.Persist = wincred.PersistLocalMachine
return cred.Write()
}
func (operatingSystemKeyring) Get(service string) ([]byte, error) {
cred, err := wincred.GetGenericCredential(service)
if err != nil {
if errors.Is(err, syscall.ERROR_NOT_FOUND) {
return nil, os.ErrNotExist
}
return nil, err
}
return cred.CredentialBlob, nil
}
func (operatingSystemKeyring) Delete(service string) error {
cred, err := wincred.GetGenericCredential(service)
if err != nil {
if errors.Is(err, syscall.ERROR_NOT_FOUND) {
return os.ErrNotExist
}
return err
}
return cred.Delete()
}
@@ -0,0 +1,74 @@
//go:build windows
package sessionstore_test
import (
"encoding/json"
"net/url"
"os"
"testing"
"github.com/danieljoos/wincred"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/cli/sessionstore"
)
func readRawKeychainCredential(t *testing.T, serviceName string) []byte {
t.Helper()
winCred, err := wincred.GetGenericCredential(serviceName)
if err != nil {
t.Fatal(err)
}
return winCred.CredentialBlob
}
func TestWindowsKeyring_WriteReadDelete(t *testing.T) {
t.Parallel()
const testURL = "http://127.0.0.1:1337"
srvURL, err := url.Parse(testURL)
require.NoError(t, err)
serviceName := keyringTestServiceName(t)
backend := sessionstore.NewKeyringWithService(serviceName)
t.Cleanup(func() { _ = backend.Delete(srvURL) })
// Verify no token exists initially
_, err = backend.Read(srvURL)
require.ErrorIs(t, err, os.ErrNotExist)
// Write a token
const inputToken = "test-token-12345"
err = backend.Write(srvURL, inputToken)
require.NoError(t, err)
// Verify the credential is stored in Windows Credential Manager with correct format
winCred, err := wincred.GetGenericCredential(serviceName)
require.NoError(t, err, "getting windows credential")
storedCreds := make(storedCredentials)
err = json.Unmarshal(winCred.CredentialBlob, &storedCreds)
require.NoError(t, err, "unmarshalling stored credentials")
// Verify the stored values
require.Len(t, storedCreds, 1)
cred, ok := storedCreds[srvURL.Host]
require.True(t, ok, "credential for URL should exist")
require.Equal(t, inputToken, cred.APIToken)
require.Equal(t, srvURL.Host, cred.CoderURL)
// Read the token back
token, err := backend.Read(srvURL)
require.NoError(t, err)
require.Equal(t, inputToken, token)
// Delete the token
err = backend.Delete(srvURL)
require.NoError(t, err)
// Verify token is deleted
_, err = backend.Read(srvURL)
require.ErrorIs(t, err, os.ErrNotExist)
}
+14 -2
View File
@@ -1,6 +1,7 @@
package cli
import (
"context"
"sort"
"sync"
@@ -14,6 +15,17 @@ import (
"github.com/coder/serpent"
)
// showSDKClient is the subset of codersdk.Client that the show command uses.
type showSDKClient interface {
workspaceGetterByName
BuildInfo(context.Context) (codersdk.BuildInfoResponse, error)
WorkspaceAgentListeningPorts(context.Context, uuid.UUID) (codersdk.WorkspaceAgentListeningPortsResponse, error)
WorkspaceAgentListContainers(context.Context, uuid.UUID, map[string]string) (codersdk.WorkspaceAgentListContainersResponse, error)
}
// ensure methods track the SDK
var _ showSDKClient = &codersdk.Client{}
func (r *RootCmd) show() *serpent.Command {
var details bool
return &serpent.Command{
@@ -31,7 +43,7 @@ func (r *RootCmd) show() *serpent.Command {
serpent.RequireNArgs(1),
),
Handler: func(inv *serpent.Invocation) error {
client, err := r.InitClient(inv)
client, err := GetClient[showSDKClient](r, inv)
if err != nil {
return err
}
@@ -62,7 +74,7 @@ func (r *RootCmd) show() *serpent.Command {
}
}
func fetchRuntimeResources(inv *serpent.Invocation, client *codersdk.Client, resources ...codersdk.WorkspaceResource) (map[uuid.UUID]codersdk.WorkspaceAgentListeningPortsResponse, map[uuid.UUID]codersdk.WorkspaceAgentListContainersResponse) {
func fetchRuntimeResources(inv *serpent.Invocation, client showSDKClient, resources ...codersdk.WorkspaceResource) (map[uuid.UUID]codersdk.WorkspaceAgentListeningPortsResponse, map[uuid.UUID]codersdk.WorkspaceAgentListContainersResponse) {
ports := make(map[uuid.UUID]codersdk.WorkspaceAgentListeningPortsResponse)
devcontainers := make(map[uuid.UUID]codersdk.WorkspaceAgentListContainersResponse)
var wg sync.WaitGroup
+69 -15
View File
@@ -2,6 +2,7 @@ package cli_test
import (
"bytes"
"context"
"testing"
"time"
@@ -12,7 +13,6 @@ import (
"github.com/coder/coder/v2/agent/agentcontainers"
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/cli/cliui"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/codersdk"
"github.com/coder/coder/v2/pty/ptytest"
)
@@ -21,21 +21,36 @@ func TestShow(t *testing.T) {
t.Parallel()
t.Run("Exists", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
owner := coderdtest.CreateFirstUser(t, client)
member, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID)
version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, completeWithAgent())
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID)
workspace := coderdtest.CreateWorkspace(t, member, template.ID)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
args := []string{
"show",
workspace.Name,
agentID := uuid.UUID{1}
workspaceID := uuid.UUID{2}
workspace := codersdk.Workspace{
Name: "test",
ID: workspaceID,
LatestBuild: codersdk.WorkspaceBuild{
Status: codersdk.WorkspaceStatusRunning,
Resources: []codersdk.WorkspaceResource{
{
Name: "main",
Type: "compute",
Agents: []codersdk.WorkspaceAgent{
{Name: "smith", ID: agentID, Architecture: "i386", OperatingSystem: "linux"},
},
},
},
},
}
inv, root := clitest.New(t, args...)
clitest.SetupConfig(t, member, root)
fSDK := &fakeShowSDK{
t: t,
expectedOwner: codersdk.Me,
returnedWorkspace: workspace,
expectedAgentID: agentID,
expectedContainerLabels: map[string]string{
agentcontainers.DevcontainerConfigFileLabel: "",
agentcontainers.DevcontainerLocalFolderLabel: "",
},
}
inv, _ := clitest.NewWithSDKOverride(t, fSDK, "show", workspace.Name)
doneChan := make(chan struct{})
pty := ptytest.New(t).Attach(inv)
go func() {
@@ -61,6 +76,45 @@ func TestShow(t *testing.T) {
})
}
type fakeShowSDK struct {
t *testing.T
expectedOwner string
returnedWorkspace codersdk.Workspace
expectedAgentID uuid.UUID
expectedContainerLabels map[string]string
}
func (f *fakeShowSDK) WorkspaceByOwnerAndName(_ context.Context, owner string, name string, _ codersdk.WorkspaceOptions) (codersdk.Workspace, error) {
assert.Equal(f.t, f.expectedOwner, owner)
assert.Equal(f.t, f.returnedWorkspace.Name, name)
return f.returnedWorkspace, nil
}
func (*fakeShowSDK) BuildInfo(_ context.Context) (codersdk.BuildInfoResponse, error) {
return codersdk.BuildInfoResponse{
Version: "test-version",
}, nil
}
func (f *fakeShowSDK) WorkspaceAgentListeningPorts(_ context.Context, u uuid.UUID) (codersdk.WorkspaceAgentListeningPortsResponse, error) {
assert.Equal(f.t, f.expectedAgentID, u)
return codersdk.WorkspaceAgentListeningPortsResponse{
Ports: []codersdk.WorkspaceAgentListeningPort{
{
ProcessName: "postgres",
Port: 5432,
Network: "tcp",
},
},
}, nil
}
func (f *fakeShowSDK) WorkspaceAgentListContainers(_ context.Context, u uuid.UUID, m map[string]string) (codersdk.WorkspaceAgentListContainersResponse, error) {
assert.Equal(f.t, f.expectedAgentID, u)
assert.Equal(f.t, f.expectedContainerLabels, m)
return codersdk.WorkspaceAgentListContainersResponse{}, nil
}
func TestShowDevcontainers_Golden(t *testing.T) {
t.Parallel()
+5
View File
@@ -108,6 +108,11 @@ variables or flags.
--url url, $CODER_URL
URL to a deployment.
--use-keyring bool, $CODER_USE_KEYRING
Store and retrieve session tokens using the operating system keyring.
Currently only supported on Windows. By default, tokens are stored in
plain text files.
-v, --verbose bool, $CODER_VERBOSE
Enable verbose output.
+2 -1
View File
@@ -90,6 +90,7 @@
"allow_renames": false,
"favorite": false,
"next_start_at": "====[timestamp]=====",
"is_prebuild": false
"is_prebuild": false,
"task_id": null
}
]
+4
View File
@@ -5,6 +5,10 @@ USAGE:
Authenticate with Coder deployment
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.
OPTIONS:
--first-user-email string, $CODER_FIRST_USER_EMAIL
Specifies an email address to use if creating the first user for the
+1 -1
View File
@@ -7,7 +7,7 @@
"last_seen_at": "====[timestamp]=====",
"name": "test-daemon",
"version": "v0.0.0-devel",
"api_version": "1.11",
"api_version": "1.12",
"provisioners": [
"echo"
],
+40
View File
@@ -80,6 +80,46 @@ OPTIONS:
Periodically check for new releases of Coder and inform the owner. The
check is performed once per day.
AIBRIDGE OPTIONS:
--aibridge-inject-coder-mcp-tools bool, $CODER_AIBRIDGE_INJECT_CODER_MCP_TOOLS (default: false)
Whether to inject Coder's MCP tools into intercepted AI Bridge
requests (requires the "oauth2" and "mcp-server-http" experiments to
be enabled).
--aibridge-anthropic-base-url string, $CODER_AIBRIDGE_ANTHROPIC_BASE_URL (default: https://api.anthropic.com/)
The base URL of the Anthropic API.
--aibridge-anthropic-key string, $CODER_AIBRIDGE_ANTHROPIC_KEY
The key to authenticate against the Anthropic API.
--aibridge-bedrock-access-key string, $CODER_AIBRIDGE_BEDROCK_ACCESS_KEY
The access key to authenticate against the AWS Bedrock API.
--aibridge-bedrock-access-key-secret string, $CODER_AIBRIDGE_BEDROCK_ACCESS_KEY_SECRET
The access key secret to use with the access key to authenticate
against the AWS Bedrock API.
--aibridge-bedrock-model string, $CODER_AIBRIDGE_BEDROCK_MODEL (default: global.anthropic.claude-sonnet-4-5-20250929-v1:0)
The model to use when making requests to the AWS Bedrock API.
--aibridge-bedrock-region string, $CODER_AIBRIDGE_BEDROCK_REGION
The AWS Bedrock API region.
--aibridge-bedrock-small-fastmodel string, $CODER_AIBRIDGE_BEDROCK_SMALL_FAST_MODEL (default: global.anthropic.claude-haiku-4-5-20251001-v1:0)
The small fast model to use when making requests to the AWS Bedrock
API. Claude Code uses Haiku-class models to perform background tasks.
See
https://docs.claude.com/en/docs/claude-code/settings#environment-variables.
--aibridge-enabled bool, $CODER_AIBRIDGE_ENABLED (default: false)
Whether to start an in-memory aibridged instance.
--aibridge-openai-base-url string, $CODER_AIBRIDGE_OPENAI_BASE_URL (default: https://api.openai.com/v1/)
The base URL of the OpenAI API.
--aibridge-openai-key string, $CODER_AIBRIDGE_OPENAI_KEY
The key to authenticate against the OpenAI API.
CLIENT OPTIONS:
These options change the behavior of how clients interact with the Coder.
Clients include the Coder CLI, Coder Desktop, IDE extensions, and the web UI.
+5 -2
View File
@@ -714,8 +714,7 @@ workspace_prebuilds:
# (default: 3, type: int)
failure_hard_limit: 3
aibridge:
# Whether to start an in-memory aibridged instance ("aibridge" experiment must be
# enabled, too).
# Whether to start an in-memory aibridged instance.
# (default: false, type: bool)
enabled: false
# The base URL of the OpenAI API.
@@ -748,3 +747,7 @@ aibridge:
# https://docs.claude.com/en/docs/claude-code/settings#environment-variables.
# (default: global.anthropic.claude-haiku-4-5-20251001-v1:0, type: string)
bedrock_small_fast_model: global.anthropic.claude-haiku-4-5-20251001-v1:0
# Whether to inject Coder's MCP tools into intercepted AI Bridge requests
# (requires the "oauth2" and "mcp-server-http" experiments to be enabled).
# (default: false, type: bool)
inject_coder_mcp_tools: false
+102 -74
View File
@@ -7,13 +7,13 @@ import (
"net/http"
"net/url"
"slices"
"strings"
"time"
"github.com/google/uuid"
"golang.org/x/xerrors"
"cdr.dev/slog"
"github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/dbtime"
@@ -24,62 +24,13 @@ import (
"github.com/coder/coder/v2/coderd/rbac/policy"
"github.com/coder/coder/v2/coderd/searchquery"
"github.com/coder/coder/v2/coderd/taskname"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/coderd/util/slice"
"github.com/coder/coder/v2/codersdk"
aiagentapi "github.com/coder/agentapi-sdk-go"
)
// This endpoint is experimental and not guaranteed to be stable, so we're not
// generating public-facing documentation for it.
func (api *API) aiTasksPrompts(rw http.ResponseWriter, r *http.Request) {
ctx := r.Context()
buildIDsParam := r.URL.Query().Get("build_ids")
if buildIDsParam == "" {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: "build_ids query parameter is required",
})
return
}
// Parse build IDs
buildIDStrings := strings.Split(buildIDsParam, ",")
buildIDs := make([]uuid.UUID, 0, len(buildIDStrings))
for _, idStr := range buildIDStrings {
id, err := uuid.Parse(strings.TrimSpace(idStr))
if err != nil {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf("Invalid build ID format: %s", idStr),
Detail: err.Error(),
})
return
}
buildIDs = append(buildIDs, id)
}
parameters, err := api.Database.GetWorkspaceBuildParametersByBuildIDs(ctx, buildIDs)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching workspace build parameters.",
Detail: err.Error(),
})
return
}
promptsByBuildID := make(map[string]string, len(parameters))
for _, param := range parameters {
if param.Name != codersdk.AITaskPromptParameterName {
continue
}
buildID := param.WorkspaceBuildID.String()
promptsByBuildID[buildID] = param.Value
}
httpapi.Write(ctx, rw, http.StatusOK, codersdk.AITasksPromptsResponse{
Prompts: promptsByBuildID,
})
}
// @Summary Create a new AI task
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
// @ID create-task
@@ -143,7 +94,7 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
if !templateVersion.HasAITask.Valid || !templateVersion.HasAITask.Bool {
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
Message: fmt.Sprintf(`Template does not have required parameter %q`, codersdk.AITaskPromptParameterName),
Message: `Template does not have a valid "coder_ai_task" resource.`,
})
return
}
@@ -174,13 +125,31 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
}
}
// Check if the template defines the AI Prompt parameter.
templateParams, err := api.Database.GetTemplateVersionParameters(ctx, req.TemplateVersionID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
Message: "Internal error fetching template parameters.",
Detail: err.Error(),
})
return
}
var richParams []codersdk.WorkspaceBuildParameter
if _, hasAIPromptParam := slice.Find(templateParams, func(param database.TemplateVersionParameter) bool {
return param.Name == codersdk.AITaskPromptParameterName
}); hasAIPromptParam {
// Only add the AI Prompt parameter if the template defines it.
richParams = []codersdk.WorkspaceBuildParameter{
{Name: codersdk.AITaskPromptParameterName, Value: req.Input},
}
}
createReq := codersdk.CreateWorkspaceRequest{
Name: taskName,
TemplateVersionID: req.TemplateVersionID,
TemplateVersionPresetID: req.TemplateVersionPresetID,
RichParameterValues: []codersdk.WorkspaceBuildParameter{
{Name: codersdk.AITaskPromptParameterName, Value: req.Input},
},
RichParameterValues: richParams,
}
var owner workspaceOwner
@@ -303,15 +272,21 @@ func (api *API) tasksCreate(rw http.ResponseWriter, r *http.Request) {
func taskFromDBTaskAndWorkspace(dbTask database.Task, ws codersdk.Workspace) codersdk.Task {
var taskAgentLifecycle *codersdk.WorkspaceAgentLifecycle
var taskAgentHealth *codersdk.WorkspaceAgentHealth
var taskAppHealth *codersdk.WorkspaceAppHealth
// If we have an agent ID from the task, find the agent details in the
// workspace.
if dbTask.WorkspaceAgentLifecycleState.Valid {
taskAgentLifecycle = ptr.Ref(codersdk.WorkspaceAgentLifecycle(dbTask.WorkspaceAgentLifecycleState.WorkspaceAgentLifecycleState))
}
if dbTask.WorkspaceAppHealth.Valid {
taskAppHealth = ptr.Ref(codersdk.WorkspaceAppHealth(dbTask.WorkspaceAppHealth.WorkspaceAppHealth))
}
// If we have an agent ID from the task, find the agent health info
if dbTask.WorkspaceAgentID.Valid {
findTaskAgentLoop:
for _, resource := range ws.LatestBuild.Resources {
for _, agent := range resource.Agents {
if agent.ID == dbTask.WorkspaceAgentID.UUID {
taskAgentLifecycle = &agent.LifecycleState
taskAgentHealth = &agent.Health
break findTaskAgentLoop
}
@@ -319,21 +294,7 @@ func taskFromDBTaskAndWorkspace(dbTask database.Task, ws codersdk.Workspace) cod
}
}
// Ignore 'latest app status' if it is older than the latest build and the
// latest build is a 'start' transition. This ensures that you don't show a
// stale app status from a previous build. For stop transitions, there is
// still value in showing the latest app status.
var currentState *codersdk.TaskStateEntry
if ws.LatestAppStatus != nil {
if ws.LatestBuild.Transition != codersdk.WorkspaceTransitionStart || ws.LatestAppStatus.CreatedAt.After(ws.LatestBuild.CreatedAt) {
currentState = &codersdk.TaskStateEntry{
Timestamp: ws.LatestAppStatus.CreatedAt,
State: codersdk.TaskState(ws.LatestAppStatus.State),
Message: ws.LatestAppStatus.Message,
URI: ws.LatestAppStatus.URI,
}
}
}
currentState := deriveTaskCurrentState(dbTask, ws, taskAgentLifecycle, taskAppHealth)
return codersdk.Task{
ID: dbTask.ID,
@@ -363,6 +324,73 @@ func taskFromDBTaskAndWorkspace(dbTask database.Task, ws codersdk.Workspace) cod
}
}
// deriveTaskCurrentState determines the current state of a task based on the
// workspace's latest app status and initialization phase.
// Returns nil if no valid state can be determined.
func deriveTaskCurrentState(
dbTask database.Task,
ws codersdk.Workspace,
taskAgentLifecycle *codersdk.WorkspaceAgentLifecycle,
taskAppHealth *codersdk.WorkspaceAppHealth,
) *codersdk.TaskStateEntry {
var currentState *codersdk.TaskStateEntry
// Ignore 'latest app status' if it is older than the latest build and the
// latest build is a 'start' transition. This ensures that you don't show a
// stale app status from a previous build. For stop transitions, there is
// still value in showing the latest app status.
if ws.LatestAppStatus != nil {
if ws.LatestBuild.Transition != codersdk.WorkspaceTransitionStart || ws.LatestAppStatus.CreatedAt.After(ws.LatestBuild.CreatedAt) {
currentState = &codersdk.TaskStateEntry{
Timestamp: ws.LatestAppStatus.CreatedAt,
State: codersdk.TaskState(ws.LatestAppStatus.State),
Message: ws.LatestAppStatus.Message,
URI: ws.LatestAppStatus.URI,
}
}
}
// If no valid agent state was found for the current build and the task is initializing,
// provide a descriptive initialization message.
if currentState == nil && dbTask.Status == database.TaskStatusInitializing {
message := "Initializing workspace"
switch {
case ws.LatestBuild.Status == codersdk.WorkspaceStatusPending ||
ws.LatestBuild.Status == codersdk.WorkspaceStatusStarting:
message = fmt.Sprintf("Workspace is %s", ws.LatestBuild.Status)
case taskAgentLifecycle != nil:
switch {
case *taskAgentLifecycle == codersdk.WorkspaceAgentLifecycleCreated:
message = "Agent is connecting"
case *taskAgentLifecycle == codersdk.WorkspaceAgentLifecycleStarting:
message = "Agent is starting"
case *taskAgentLifecycle == codersdk.WorkspaceAgentLifecycleReady:
if taskAppHealth != nil && *taskAppHealth == codersdk.WorkspaceAppHealthInitializing {
message = "App is initializing"
} else {
// In case the workspace app is not initializing,
// the overall task status should be updated accordingly
message = "Initializing workspace applications"
}
default:
// In case the workspace agent is not initializing,
// the overall task status should be updated accordingly
message = "Initializing workspace agent"
}
}
currentState = &codersdk.TaskStateEntry{
Timestamp: ws.LatestBuild.CreatedAt,
State: codersdk.TaskStateWorking,
Message: message,
URI: "",
}
}
return currentState
}
// @Summary List AI tasks
// @Description: EXPERIMENTAL: this endpoint is experimental and not guaranteed to be stable.
// @ID list-tasks
+223
View File
@@ -0,0 +1,223 @@
package coderd
import (
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/util/ptr"
"github.com/coder/coder/v2/codersdk"
)
func TestDeriveTaskCurrentState_Unit(t *testing.T) {
t.Parallel()
now := time.Now()
tests := []struct {
name string
task database.Task
agentLifecycle *codersdk.WorkspaceAgentLifecycle
appHealth *codersdk.WorkspaceAppHealth
latestAppStatus *codersdk.WorkspaceAppStatus
latestBuild codersdk.WorkspaceBuild
expectCurrentState bool
expectedTimestamp time.Time
expectedState codersdk.TaskState
expectedMessage string
}{
{
name: "NoAppStatus",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusActive,
},
agentLifecycle: nil,
appHealth: nil,
latestAppStatus: nil,
latestBuild: codersdk.WorkspaceBuild{
Transition: codersdk.WorkspaceTransitionStart,
CreatedAt: now,
},
expectCurrentState: false,
},
{
name: "BuildStartTransition_AppStatus_NewerThanBuild",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusActive,
},
agentLifecycle: nil,
appHealth: nil,
latestAppStatus: &codersdk.WorkspaceAppStatus{
State: codersdk.WorkspaceAppStatusStateWorking,
Message: "Task is working",
CreatedAt: now.Add(1 * time.Minute),
},
latestBuild: codersdk.WorkspaceBuild{
Transition: codersdk.WorkspaceTransitionStart,
CreatedAt: now,
},
expectCurrentState: true,
expectedTimestamp: now.Add(1 * time.Minute),
expectedState: codersdk.TaskState(codersdk.WorkspaceAppStatusStateWorking),
expectedMessage: "Task is working",
},
{
name: "BuildStartTransition_StaleAppStatus_OlderThanBuild",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusActive,
},
agentLifecycle: nil,
appHealth: nil,
latestAppStatus: &codersdk.WorkspaceAppStatus{
State: codersdk.WorkspaceAppStatusStateComplete,
Message: "Previous task completed",
CreatedAt: now.Add(-1 * time.Minute),
},
latestBuild: codersdk.WorkspaceBuild{
Transition: codersdk.WorkspaceTransitionStart,
CreatedAt: now,
},
expectCurrentState: false,
},
{
name: "BuildStopTransition",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusActive,
},
agentLifecycle: nil,
appHealth: nil,
latestAppStatus: &codersdk.WorkspaceAppStatus{
State: codersdk.WorkspaceAppStatusStateComplete,
Message: "Task completed before stop",
CreatedAt: now.Add(-1 * time.Minute),
},
latestBuild: codersdk.WorkspaceBuild{
Transition: codersdk.WorkspaceTransitionStop,
CreatedAt: now,
},
expectCurrentState: true,
expectedTimestamp: now.Add(-1 * time.Minute),
expectedState: codersdk.TaskState(codersdk.WorkspaceAppStatusStateComplete),
expectedMessage: "Task completed before stop",
},
{
name: "TaskInitializing_WorkspacePending",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusInitializing,
},
agentLifecycle: nil,
appHealth: nil,
latestAppStatus: nil,
latestBuild: codersdk.WorkspaceBuild{
Status: codersdk.WorkspaceStatusPending,
CreatedAt: now,
},
expectCurrentState: true,
expectedTimestamp: now,
expectedState: codersdk.TaskStateWorking,
expectedMessage: "Workspace is pending",
},
{
name: "TaskInitializing_WorkspaceStarting",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusInitializing,
},
agentLifecycle: nil,
appHealth: nil,
latestAppStatus: nil,
latestBuild: codersdk.WorkspaceBuild{
Status: codersdk.WorkspaceStatusStarting,
CreatedAt: now,
},
expectCurrentState: true,
expectedTimestamp: now,
expectedState: codersdk.TaskStateWorking,
expectedMessage: "Workspace is starting",
},
{
name: "TaskInitializing_AgentConnecting",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusInitializing,
},
agentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleCreated),
appHealth: nil,
latestAppStatus: nil,
latestBuild: codersdk.WorkspaceBuild{
Status: codersdk.WorkspaceStatusRunning,
CreatedAt: now,
},
expectCurrentState: true,
expectedTimestamp: now,
expectedState: codersdk.TaskStateWorking,
expectedMessage: "Agent is connecting",
},
{
name: "TaskInitializing_AgentStarting",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusInitializing,
},
agentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleStarting),
appHealth: nil,
latestAppStatus: nil,
latestBuild: codersdk.WorkspaceBuild{
Status: codersdk.WorkspaceStatusRunning,
CreatedAt: now,
},
expectCurrentState: true,
expectedTimestamp: now,
expectedState: codersdk.TaskStateWorking,
expectedMessage: "Agent is starting",
},
{
name: "TaskInitializing_AppInitializing",
task: database.Task{
ID: uuid.New(),
Status: database.TaskStatusInitializing,
},
agentLifecycle: ptr.Ref(codersdk.WorkspaceAgentLifecycleReady),
appHealth: ptr.Ref(codersdk.WorkspaceAppHealthInitializing),
latestAppStatus: nil,
latestBuild: codersdk.WorkspaceBuild{
Status: codersdk.WorkspaceStatusRunning,
CreatedAt: now,
},
expectCurrentState: true,
expectedTimestamp: now,
expectedState: codersdk.TaskStateWorking,
expectedMessage: "App is initializing",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
ws := codersdk.Workspace{
LatestBuild: tt.latestBuild,
LatestAppStatus: tt.latestAppStatus,
}
currentState := deriveTaskCurrentState(tt.task, ws, tt.agentLifecycle, tt.appHealth)
if tt.expectCurrentState {
require.NotNil(t, currentState)
assert.Equal(t, tt.expectedTimestamp.UTC(), currentState.Timestamp.UTC())
assert.Equal(t, tt.expectedState, currentState.State)
assert.Equal(t, tt.expectedMessage, currentState.Message)
} else {
assert.Nil(t, currentState)
}
})
}
}
+225 -176
View File
@@ -7,10 +7,8 @@ import (
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"unicode/utf8"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
@@ -35,128 +33,6 @@ import (
"github.com/coder/coder/v2/testutil"
)
func TestAITasksPrompts(t *testing.T) {
t.Parallel()
t.Run("EmptyBuildIDs", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{})
_ = coderdtest.CreateFirstUser(t, client)
experimentalClient := codersdk.NewExperimentalClient(client)
ctx := testutil.Context(t, testutil.WaitShort)
// Test with empty build IDs
prompts, err := experimentalClient.AITaskPrompts(ctx, []uuid.UUID{})
require.NoError(t, err)
require.Empty(t, prompts.Prompts)
})
t.Run("MultipleBuilds", func(t *testing.T) {
t.Parallel()
adminClient := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
first := coderdtest.CreateFirstUser(t, adminClient)
memberClient, _ := coderdtest.CreateAnotherUser(t, adminClient, first.OrganizationID)
ctx := testutil.Context(t, testutil.WaitLong)
// Create a template with parameters
version := coderdtest.CreateTemplateVersion(t, adminClient, first.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionPlan: []*proto.Response{{
Type: &proto.Response_Plan{
Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{
{
Name: "param1",
Type: "string",
DefaultValue: "default1",
},
{
Name: codersdk.AITaskPromptParameterName,
Type: "string",
DefaultValue: "default2",
},
},
},
},
}},
ProvisionApply: echo.ApplyComplete,
})
template := coderdtest.CreateTemplate(t, adminClient, first.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, adminClient, version.ID)
// Create two workspaces with different parameters
workspace1 := coderdtest.CreateWorkspace(t, memberClient, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
{Name: "param1", Value: "value1a"},
{Name: codersdk.AITaskPromptParameterName, Value: "value2a"},
}
})
coderdtest.AwaitWorkspaceBuildJobCompleted(t, memberClient, workspace1.LatestBuild.ID)
workspace2 := coderdtest.CreateWorkspace(t, memberClient, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
{Name: "param1", Value: "value1b"},
{Name: codersdk.AITaskPromptParameterName, Value: "value2b"},
}
})
coderdtest.AwaitWorkspaceBuildJobCompleted(t, memberClient, workspace2.LatestBuild.ID)
workspace3 := coderdtest.CreateWorkspace(t, adminClient, template.ID, func(request *codersdk.CreateWorkspaceRequest) {
request.RichParameterValues = []codersdk.WorkspaceBuildParameter{
{Name: "param1", Value: "value1c"},
{Name: codersdk.AITaskPromptParameterName, Value: "value2c"},
}
})
coderdtest.AwaitWorkspaceBuildJobCompleted(t, adminClient, workspace3.LatestBuild.ID)
allBuildIDs := []uuid.UUID{workspace1.LatestBuild.ID, workspace2.LatestBuild.ID, workspace3.LatestBuild.ID}
experimentalMemberClient := codersdk.NewExperimentalClient(memberClient)
// Test parameters endpoint as member
prompts, err := experimentalMemberClient.AITaskPrompts(ctx, allBuildIDs)
require.NoError(t, err)
// we expect 2 prompts because the member client does not have access to workspace3
// since it was created by the admin client
require.Len(t, prompts.Prompts, 2)
// Check workspace1 parameters
build1Prompt := prompts.Prompts[workspace1.LatestBuild.ID.String()]
require.Equal(t, "value2a", build1Prompt)
// Check workspace2 parameters
build2Prompt := prompts.Prompts[workspace2.LatestBuild.ID.String()]
require.Equal(t, "value2b", build2Prompt)
experimentalAdminClient := codersdk.NewExperimentalClient(adminClient)
// Test parameters endpoint as admin
// we expect 3 prompts because the admin client has access to all workspaces
prompts, err = experimentalAdminClient.AITaskPrompts(ctx, allBuildIDs)
require.NoError(t, err)
require.Len(t, prompts.Prompts, 3)
// Check workspace3 parameters
build3Prompt := prompts.Prompts[workspace3.LatestBuild.ID.String()]
require.Equal(t, "value2c", build3Prompt)
})
t.Run("NonExistentBuildIDs", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{})
_ = coderdtest.CreateFirstUser(t, client)
ctx := testutil.Context(t, testutil.WaitShort)
// Test with non-existent build IDs
nonExistentID := uuid.New()
experimentalClient := codersdk.NewExperimentalClient(client)
prompts, err := experimentalClient.AITaskPrompts(ctx, []uuid.UUID{nonExistentID})
require.NoError(t, err)
require.Empty(t, prompts.Prompts)
})
}
func TestTasks(t *testing.T) {
t.Parallel()
@@ -188,7 +64,6 @@ func TestTasks(t *testing.T) {
{
Type: &proto.Response_Plan{
Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
},
},
@@ -259,6 +134,9 @@ func TestTasks(t *testing.T) {
// Wait for the workspace to be built.
workspace, err := client.Workspace(ctx, task.WorkspaceID.UUID)
require.NoError(t, err)
if assert.True(t, workspace.TaskID.Valid, "task id should be set on workspace") {
assert.Equal(t, task.ID, workspace.TaskID.UUID, "workspace task id should match")
}
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
// List tasks via experimental API and verify the prompt and status mapping.
@@ -279,12 +157,13 @@ func TestTasks(t *testing.T) {
t.Parallel()
var (
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
ctx = testutil.Context(t, testutil.WaitLong)
user = coderdtest.CreateFirstUser(t, client)
template = createAITemplate(t, client, user)
wantPrompt = "review my code"
exp = codersdk.NewExperimentalClient(client)
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
ctx = testutil.Context(t, testutil.WaitLong)
user = coderdtest.CreateFirstUser(t, client)
anotherUser, _ = coderdtest.CreateAnotherUser(t, client, user.OrganizationID)
template = createAITemplate(t, client, user)
wantPrompt = "review my code"
exp = codersdk.NewExperimentalClient(client)
)
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
@@ -297,6 +176,9 @@ func TestTasks(t *testing.T) {
// Get the workspace and wait for it to be ready.
ws, err := client.Workspace(ctx, task.WorkspaceID.UUID)
require.NoError(t, err)
if assert.True(t, ws.TaskID.Valid, "task id should be set on workspace") {
assert.Equal(t, task.ID, ws.TaskID.UUID, "workspace task id should match")
}
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
ws = coderdtest.MustWorkspace(t, client, task.WorkspaceID.UUID)
// Assert invariant: the workspace has exactly one resource with one agent with one app.
@@ -331,6 +213,24 @@ func TestTasks(t *testing.T) {
assert.Equal(t, taskAppID, updated.WorkspaceAppID.UUID, "workspace app id should match")
assert.NotEmpty(t, updated.WorkspaceStatus, "task status should not be empty")
// Fetch the task by name and verify the same result
byName, err := exp.TaskByOwnerAndName(ctx, codersdk.Me, task.Name)
require.NoError(t, err)
require.Equal(t, byName, updated)
// Another member user should not be able to fetch the task
otherClient := codersdk.NewExperimentalClient(anotherUser)
_, err = otherClient.TaskByID(ctx, task.ID)
require.Error(t, err, "fetching task should fail by ID for another member user")
var sdkErr *codersdk.Error
require.ErrorAs(t, err, &sdkErr)
require.Equal(t, http.StatusNotFound, sdkErr.StatusCode())
// Also test by name
_, err = otherClient.TaskByOwnerAndName(ctx, task.OwnerName, task.Name)
require.Error(t, err, "fetching task should fail by name for another member user")
require.ErrorAs(t, err, &sdkErr)
require.Equal(t, http.StatusNotFound, sdkErr.StatusCode())
// Stop the workspace
coderdtest.MustTransitionWorkspace(t, client, task.WorkspaceID.UUID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop)
@@ -340,14 +240,18 @@ func TestTasks(t *testing.T) {
assert.NotNil(t, updated.CurrentState, "current state should not be nil")
assert.Equal(t, "all done", updated.CurrentState.Message)
assert.Equal(t, codersdk.TaskStateComplete, updated.CurrentState.State)
previousCurrentState := updated.CurrentState
// Start the workspace again
coderdtest.MustTransitionWorkspace(t, client, task.WorkspaceID.UUID, codersdk.WorkspaceTransitionStop, codersdk.WorkspaceTransitionStart)
// Verify that the status from the previous build is no longer present
// Verify that the status from the previous build has been cleared
// and replaced by the agent initialization status.
updated, err = exp.TaskByID(ctx, task.ID)
require.NoError(t, err)
assert.Nil(t, updated.CurrentState, "current state should be nil")
assert.NotEqual(t, previousCurrentState, updated.CurrentState)
assert.Equal(t, codersdk.TaskStateWorking, updated.CurrentState.State)
assert.NotEqual(t, "all done", updated.CurrentState.Message)
})
t.Run("Delete", func(t *testing.T) {
@@ -371,6 +275,9 @@ func TestTasks(t *testing.T) {
require.True(t, task.WorkspaceID.Valid, "task should have a workspace ID")
ws, err := client.Workspace(ctx, task.WorkspaceID.UUID)
require.NoError(t, err)
if assert.True(t, ws.TaskID.Valid, "task id should be set on workspace") {
assert.Equal(t, task.ID, ws.TaskID.UUID, "workspace task id should match")
}
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
err = exp.DeleteTask(ctx, "me", task.ID)
@@ -417,6 +324,9 @@ func TestTasks(t *testing.T) {
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
ws := coderdtest.CreateWorkspace(t, client, template.ID)
if assert.False(t, ws.TaskID.Valid, "task id should not be set on non-task workspace") {
assert.Zero(t, ws.TaskID, "non-task workspace task id should be empty")
}
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
exp := codersdk.NewExperimentalClient(client)
@@ -466,10 +376,10 @@ func TestTasks(t *testing.T) {
}
})
t.Run("NoWorkspace", func(t *testing.T) {
t.Run("DeletedWorkspace", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
client, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
user := coderdtest.CreateFirstUser(t, client)
template := createAITemplate(t, client, user)
ctx := testutil.Context(t, testutil.WaitLong)
@@ -483,14 +393,54 @@ func TestTasks(t *testing.T) {
ws, err := client.Workspace(ctx, task.WorkspaceID.UUID)
require.NoError(t, err)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
// Delete the task workspace
coderdtest.MustTransitionWorkspace(t, client, ws.ID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionDelete)
// We should still be able to fetch the task after deleting its workspace
// Mark the workspace as deleted directly in the database, bypassing provisionerd.
require.NoError(t, db.UpdateWorkspaceDeletedByID(dbauthz.AsProvisionerd(ctx), database.UpdateWorkspaceDeletedByIDParams{
ID: ws.ID,
Deleted: true,
}))
// We should still be able to fetch the task if its workspace was deleted.
// Provisionerdserver will attempt delete the related task when deleting a workspace.
// This test ensures that we can still handle the case where, for some reason, the
// task has not been marked as deleted, but the workspace has.
task, err = exp.TaskByID(ctx, task.ID)
require.NoError(t, err, "fetching a task should still work after deleting its related workspace")
require.NoError(t, err, "fetching a task should still work if its related workspace is deleted")
err = exp.DeleteTask(ctx, task.OwnerID.String(), task.ID)
require.NoError(t, err, "should be possible to delete a task with no workspace")
})
t.Run("DeletingTaskWorkspaceDeletesTask", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
user := coderdtest.CreateFirstUser(t, client)
template := createAITemplate(t, client, user)
ctx := testutil.Context(t, testutil.WaitLong)
exp := codersdk.NewExperimentalClient(client)
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
TemplateVersionID: template.ActiveVersionID,
Input: "delete me",
})
require.NoError(t, err)
require.True(t, task.WorkspaceID.Valid, "task should have a workspace ID")
ws, err := client.Workspace(ctx, task.WorkspaceID.UUID)
require.NoError(t, err)
if assert.True(t, ws.TaskID.Valid, "task id should be set on workspace") {
assert.Equal(t, task.ID, ws.TaskID.UUID, "workspace task id should match")
}
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
// When; the task workspace is deleted
coderdtest.MustTransitionWorkspace(t, client, ws.ID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionDelete)
// Then: the task associated with the workspace is also deleted
_, err = exp.TaskByID(ctx, task.ID)
require.Error(t, err, "expected an error fetching the task")
var sdkErr *codersdk.Error
require.ErrorAs(t, err, &sdkErr, "expected a codersdk.Error")
require.Equal(t, http.StatusNotFound, sdkErr.StatusCode())
})
})
t.Run("Send", func(t *testing.T) {
@@ -728,7 +678,7 @@ func TestTasks(t *testing.T) {
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
// Fetch the task by ID via experimental API and verify fields.
task, err = exp.TaskByID(ctx, task.ID)
task, err = exp.TaskByIdentifier(ctx, task.ID.String())
require.NoError(t, err)
require.NotZero(t, task.WorkspaceBuildNumber)
require.True(t, task.WorkspaceAgentID.Valid)
@@ -805,6 +755,51 @@ func TestTasksCreate(t *testing.T) {
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
user := coderdtest.CreateFirstUser(t, client)
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
HasAiTasks: true,
}}},
},
})
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
expClient := codersdk.NewExperimentalClient(client)
task, err := expClient.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
TemplateVersionID: template.ActiveVersionID,
Input: taskPrompt,
})
require.NoError(t, err)
require.True(t, task.WorkspaceID.Valid)
ws, err := client.Workspace(ctx, task.WorkspaceID.UUID)
require.NoError(t, err)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, ws.LatestBuild.ID)
assert.NotEmpty(t, task.Name)
assert.Equal(t, template.ID, task.TemplateID)
parameters, err := client.WorkspaceBuildParameters(ctx, ws.LatestBuild.ID)
require.NoError(t, err)
require.Len(t, parameters, 0)
})
t.Run("OK AIPromptBackCompat", func(t *testing.T) {
t.Parallel()
var (
ctx = testutil.Context(t, testutil.WaitShort)
taskPrompt = "Some task prompt"
)
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
user := coderdtest.CreateFirstUser(t, client)
// Given: A template with an "AI Prompt" parameter
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
Parse: echo.ParseComplete,
@@ -884,7 +879,6 @@ func TestTasksCreate(t *testing.T) {
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
}}},
},
@@ -1000,7 +994,6 @@ func TestTasksCreate(t *testing.T) {
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
}}},
},
@@ -1060,7 +1053,6 @@ func TestTasksCreate(t *testing.T) {
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
}}},
},
@@ -1097,7 +1089,6 @@ func TestTasksCreate(t *testing.T) {
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
}}},
},
@@ -1150,7 +1141,6 @@ func TestTasksCreate(t *testing.T) {
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
}}},
},
@@ -1163,7 +1153,6 @@ func TestTasksCreate(t *testing.T) {
ProvisionApply: echo.ApplyComplete,
ProvisionPlan: []*proto.Response{
{Type: &proto.Response_Plan{Plan: &proto.PlanComplete{
Parameters: []*proto.RichParameter{{Name: codersdk.AITaskPromptParameterName, Type: "string"}},
HasAiTasks: true,
}}},
},
@@ -1200,6 +1189,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent bool
notificationTemplate uuid.UUID
taskPrompt string
agentLifecycle database.WorkspaceAgentLifecycleState
}{
// Should not send a notification when the agent app is not an AI task.
{
@@ -1247,6 +1237,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskIdle,
taskPrompt: "InitialTemplateTaskIdle",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Should send TemplateTaskWorking when the AI task transitions to 'Working' from 'Idle'.
{
@@ -1260,6 +1251,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskWorking,
taskPrompt: "TemplateTaskWorkingFromIdle",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Should send TemplateTaskIdle when the AI task transitions to 'Idle'.
{
@@ -1270,6 +1262,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskIdle,
taskPrompt: "TemplateTaskIdle",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Long task prompts should be truncated to 160 characters.
{
@@ -1280,6 +1273,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskIdle,
taskPrompt: "This is a very long task prompt that should be truncated to 160 characters. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Should send TemplateTaskCompleted when the AI task transitions to 'Complete'.
{
@@ -1290,6 +1284,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskCompleted,
taskPrompt: "TemplateTaskCompleted",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Should send TemplateTaskFailed when the AI task transitions to 'Failure'.
{
@@ -1300,6 +1295,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskFailed,
taskPrompt: "TemplateTaskFailed",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Should send TemplateTaskCompleted when the AI task transitions from 'Idle' to 'Complete'.
{
@@ -1310,6 +1306,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskCompleted,
taskPrompt: "TemplateTaskCompletedFromIdle",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Should send TemplateTaskFailed when the AI task transitions from 'Idle' to 'Failure'.
{
@@ -1320,6 +1317,7 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskFailed,
taskPrompt: "TemplateTaskFailedFromIdle",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
// Should NOT send notification when transitioning from 'Complete' to 'Complete' (no change).
{
@@ -1339,6 +1337,37 @@ func TestTasksNotification(t *testing.T) {
isNotificationSent: false,
taskPrompt: "NoNotificationFailureToFailure",
},
// Should NOT send notification when agent is in 'starting' lifecycle state (agent startup).
{
name: "AgentStarting_NoNotification",
latestAppStatuses: nil,
newAppStatus: codersdk.WorkspaceAppStatusStateIdle,
isAITask: true,
isNotificationSent: false,
taskPrompt: "AgentStarting_NoNotification",
agentLifecycle: database.WorkspaceAgentLifecycleStateStarting,
},
// Should NOT send notification when agent is in 'created' lifecycle state (agent not started).
{
name: "AgentCreated_NoNotification",
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateWorking},
newAppStatus: codersdk.WorkspaceAppStatusStateIdle,
isAITask: true,
isNotificationSent: false,
taskPrompt: "AgentCreated_NoNotification",
agentLifecycle: database.WorkspaceAgentLifecycleStateCreated,
},
// Should send notification when agent is in 'ready' lifecycle state (agent fully started).
{
name: "AgentReady_SendNotification",
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateWorking},
newAppStatus: codersdk.WorkspaceAppStatusStateIdle,
isAITask: true,
isNotificationSent: true,
notificationTemplate: notifications.TemplateTaskIdle,
taskPrompt: "AgentReady_SendNotification",
agentLifecycle: database.WorkspaceAgentLifecycleStateReady,
},
} {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
@@ -1357,31 +1386,57 @@ func TestTasksNotification(t *testing.T) {
// Given: a workspace build with an agent containing an App
workspaceAgentAppID := uuid.New()
workspaceBuildID := uuid.New()
workspaceBuildSeed := database.WorkspaceBuild{
ID: workspaceBuildID,
}
if tc.isAITask {
workspaceBuildSeed = database.WorkspaceBuild{
ID: workspaceBuildID,
// AI Task configuration
HasAITask: sql.NullBool{Bool: true, Valid: true},
AITaskSidebarAppID: uuid.NullUUID{UUID: workspaceAgentAppID, Valid: true},
}
}
workspaceBuild := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
workspaceBuilder := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{
OrganizationID: ownerUser.OrganizationID,
OwnerID: memberUser.ID,
}).Seed(workspaceBuildSeed).Params(database.WorkspaceBuildParameter{
WorkspaceBuildID: workspaceBuildID,
Name: codersdk.AITaskPromptParameterName,
Value: tc.taskPrompt,
}).WithAgent(func(agent []*proto.Agent) []*proto.Agent {
agent[0].Apps = []*proto.App{{
Id: workspaceAgentAppID.String(),
Slug: "ccw",
}}
return agent
}).Do()
}).Seed(database.WorkspaceBuild{
ID: workspaceBuildID,
})
if tc.isAITask {
workspaceBuilder = workspaceBuilder.
WithTask(database.TaskTable{
Prompt: tc.taskPrompt,
}, &proto.App{
Id: workspaceAgentAppID.String(),
Slug: "ccw",
})
} else {
workspaceBuilder = workspaceBuilder.
WithAgent(func(agent []*proto.Agent) []*proto.Agent {
agent[0].Apps = []*proto.App{{
Id: workspaceAgentAppID.String(),
Slug: "ccw",
}}
return agent
})
}
workspaceBuild := workspaceBuilder.Do()
// Given: set the agent lifecycle state if specified
if tc.agentLifecycle != "" {
workspace := coderdtest.MustWorkspace(t, client, workspaceBuild.Workspace.ID)
agentID := workspace.LatestBuild.Resources[0].Agents[0].ID
var (
startedAt sql.NullTime
readyAt sql.NullTime
)
if tc.agentLifecycle == database.WorkspaceAgentLifecycleStateReady {
startedAt = sql.NullTime{Time: dbtime.Now(), Valid: true}
readyAt = sql.NullTime{Time: dbtime.Now(), Valid: true}
} else if tc.agentLifecycle == database.WorkspaceAgentLifecycleStateStarting {
startedAt = sql.NullTime{Time: dbtime.Now(), Valid: true}
}
// nolint:gocritic // This is a system restricted operation for test setup.
err := db.UpdateWorkspaceAgentLifecycleStateByID(dbauthz.AsSystemRestricted(ctx), database.UpdateWorkspaceAgentLifecycleStateByIDParams{
ID: agentID,
LifecycleState: tc.agentLifecycle,
StartedAt: startedAt,
ReadyAt: readyAt,
})
require.NoError(t, err)
}
// Given: the workspace agent app has previous statuses
agentClient := agentsdk.New(client.URL, agentsdk.WithFixedToken(workspaceBuild.AgentToken))
@@ -1422,13 +1477,7 @@ func TestTasksNotification(t *testing.T) {
require.Len(t, sent, 1)
require.Equal(t, memberUser.ID, sent[0].UserID)
require.Len(t, sent[0].Labels, 2)
// NOTE: len(string) is the number of bytes in the string, not the number of runes.
require.LessOrEqual(t, utf8.RuneCountInString(sent[0].Labels["task"]), 160)
if len(tc.taskPrompt) > 160 {
require.Contains(t, tc.taskPrompt, strings.TrimSuffix(sent[0].Labels["task"], "…"))
} else {
require.Equal(t, tc.taskPrompt, sent[0].Labels["task"])
}
require.Equal(t, workspaceBuild.Task.Name, sent[0].Labels["task"])
require.Equal(t, workspace.Name, sent[0].Labels["workspace"])
} else {
// Then: No notification is sent
+89 -13
View File
@@ -85,7 +85,7 @@ const docTemplate = `{
}
}
},
"/api/experimental/aibridge/interceptions": {
"/aibridge/interceptions": {
"get": {
"security": [
{
@@ -6002,6 +6002,41 @@ const docTemplate = `{
}
}
},
"/templates/{template}/prebuilds/invalidate": {
"post": {
"security": [
{
"CoderSessionToken": []
}
],
"produces": [
"application/json"
],
"tags": [
"Enterprise"
],
"summary": "Invalidate presets for template",
"operationId": "invalidate-presets-for-template",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "Template ID",
"name": "template",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.InvalidatePresetsResponse"
}
}
}
}
},
"/templates/{template}/versions": {
"get": {
"security": [
@@ -11700,6 +11735,9 @@ const docTemplate = `{
"enabled": {
"type": "boolean"
},
"inject_coder_mcp_tools": {
"type": "boolean"
},
"openai": {
"$ref": "#/definitions/codersdk.AIBridgeOpenAIConfig"
}
@@ -11708,6 +11746,9 @@ const docTemplate = `{
"codersdk.AIBridgeInterception": {
"type": "object",
"properties": {
"api_key_id": {
"type": "string"
},
"ended_at": {
"type": "string",
"format": "date-time"
@@ -14317,15 +14358,15 @@ const docTemplate = `{
"oauth2",
"mcp-server-http",
"workspace-sharing",
"aibridge"
"terraform-directory-reuse"
],
"x-enum-comments": {
"ExperimentAIBridge": "Enables AI Bridge functionality.",
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.",
"ExperimentExample": "This isn't used for anything.",
"ExperimentMCPServerHTTP": "Enables the MCP HTTP server functionality.",
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
"ExperimentOAuth2": "Enables OAuth2 provider functionality.",
"ExperimentTerraformWorkspace": "Enables reuse of existing terraform directory for builds",
"ExperimentWebPush": "Enables web push notifications through the browser.",
"ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.",
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
@@ -14339,7 +14380,7 @@ const docTemplate = `{
"ExperimentOAuth2",
"ExperimentMCPServerHTTP",
"ExperimentWorkspaceSharing",
"ExperimentAIBridge"
"ExperimentTerraformWorkspace"
]
},
"codersdk.ExternalAPIKeyScopes": {
@@ -14883,6 +14924,31 @@ const docTemplate = `{
"InsightsReportIntervalWeek"
]
},
"codersdk.InvalidatePresetsResponse": {
"type": "object",
"properties": {
"invalidated": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.InvalidatedPreset"
}
}
}
},
"codersdk.InvalidatedPreset": {
"type": "object",
"properties": {
"preset_name": {
"type": "string"
},
"template_name": {
"type": "string"
},
"template_version_name": {
"type": "string"
}
}
},
"codersdk.IssueReconnectingPTYSignedTokenRequest": {
"type": "object",
"required": [
@@ -15438,6 +15504,9 @@ const docTemplate = `{
"type": "string"
}
},
"revocation_endpoint": {
"type": "string"
},
"scopes_supported": {
"type": "array",
"items": {
@@ -18129,6 +18198,9 @@ const docTemplate = `{
},
"use_classic_parameter_flow": {
"type": "boolean"
},
"use_terraform_workspace_cache": {
"type": "boolean"
}
}
},
@@ -19057,6 +19129,10 @@ const docTemplate = `{
"use_classic_parameter_flow": {
"description": "UseClassicParameterFlow is a flag that switches the default behavior to use the classic\nparameter flow when creating a workspace. This only affects deployments with the experiment\n\"dynamic-parameters\" enabled. This setting will live for a period after the experiment is\nmade the default.\nAn \"opt-out\" is present in case the new feature breaks some existing templates.",
"type": "boolean"
},
"use_terraform_workspace_cache": {
"description": "UseTerraformWorkspaceCache allows optionally specifying whether to use cached\nterraform directories for workspaces created from this template. This field\nonly applies when the correct experiment is enabled. This field is subject to\nbeing removed in the future.",
"type": "boolean"
}
}
},
@@ -19715,6 +19791,14 @@ const docTemplate = `{
"description": "OwnerName is the username of the owner of the workspace.",
"type": "string"
},
"task_id": {
"description": "TaskID, if set, indicates that the workspace is relevant to the given codersdk.Task.",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"template_active_version_id": {
"type": "string",
"format": "uuid"
@@ -20521,11 +20605,6 @@ const docTemplate = `{
"codersdk.WorkspaceBuild": {
"type": "object",
"properties": {
"ai_task_sidebar_app_id": {
"description": "Deprecated: This field has been replaced with ` + "`" + `TaskAppID` + "`" + `",
"type": "string",
"format": "uuid"
},
"build_number": {
"type": "integer"
},
@@ -20541,6 +20620,7 @@ const docTemplate = `{
"format": "date-time"
},
"has_ai_task": {
"description": "Deprecated: This field has been deprecated in favor of Task WorkspaceID.",
"type": "boolean"
},
"has_external_agent": {
@@ -20604,10 +20684,6 @@ const docTemplate = `{
}
]
},
"task_app_id": {
"type": "string",
"format": "uuid"
},
"template_version_id": {
"type": "string",
"format": "uuid"
+85 -13
View File
@@ -65,7 +65,7 @@
}
}
},
"/api/experimental/aibridge/interceptions": {
"/aibridge/interceptions": {
"get": {
"security": [
{
@@ -5309,6 +5309,37 @@
}
}
},
"/templates/{template}/prebuilds/invalidate": {
"post": {
"security": [
{
"CoderSessionToken": []
}
],
"produces": ["application/json"],
"tags": ["Enterprise"],
"summary": "Invalidate presets for template",
"operationId": "invalidate-presets-for-template",
"parameters": [
{
"type": "string",
"format": "uuid",
"description": "Template ID",
"name": "template",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.InvalidatePresetsResponse"
}
}
}
}
},
"/templates/{template}/versions": {
"get": {
"security": [
@@ -10396,6 +10427,9 @@
"enabled": {
"type": "boolean"
},
"inject_coder_mcp_tools": {
"type": "boolean"
},
"openai": {
"$ref": "#/definitions/codersdk.AIBridgeOpenAIConfig"
}
@@ -10404,6 +10438,9 @@
"codersdk.AIBridgeInterception": {
"type": "object",
"properties": {
"api_key_id": {
"type": "string"
},
"ended_at": {
"type": "string",
"format": "date-time"
@@ -12924,15 +12961,15 @@
"oauth2",
"mcp-server-http",
"workspace-sharing",
"aibridge"
"terraform-directory-reuse"
],
"x-enum-comments": {
"ExperimentAIBridge": "Enables AI Bridge functionality.",
"ExperimentAutoFillParameters": "This should not be taken out of experiments until we have redesigned the feature.",
"ExperimentExample": "This isn't used for anything.",
"ExperimentMCPServerHTTP": "Enables the MCP HTTP server functionality.",
"ExperimentNotifications": "Sends notifications via SMTP and webhooks following certain events.",
"ExperimentOAuth2": "Enables OAuth2 provider functionality.",
"ExperimentTerraformWorkspace": "Enables reuse of existing terraform directory for builds",
"ExperimentWebPush": "Enables web push notifications through the browser.",
"ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.",
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
@@ -12946,7 +12983,7 @@
"ExperimentOAuth2",
"ExperimentMCPServerHTTP",
"ExperimentWorkspaceSharing",
"ExperimentAIBridge"
"ExperimentTerraformWorkspace"
]
},
"codersdk.ExternalAPIKeyScopes": {
@@ -13481,6 +13518,31 @@
"InsightsReportIntervalWeek"
]
},
"codersdk.InvalidatePresetsResponse": {
"type": "object",
"properties": {
"invalidated": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.InvalidatedPreset"
}
}
}
},
"codersdk.InvalidatedPreset": {
"type": "object",
"properties": {
"preset_name": {
"type": "string"
},
"template_name": {
"type": "string"
},
"template_version_name": {
"type": "string"
}
}
},
"codersdk.IssueReconnectingPTYSignedTokenRequest": {
"type": "object",
"required": ["agentID", "url"],
@@ -13992,6 +14054,9 @@
"type": "string"
}
},
"revocation_endpoint": {
"type": "string"
},
"scopes_supported": {
"type": "array",
"items": {
@@ -16604,6 +16669,9 @@
},
"use_classic_parameter_flow": {
"type": "boolean"
},
"use_terraform_workspace_cache": {
"type": "boolean"
}
}
},
@@ -17488,6 +17556,10 @@
"use_classic_parameter_flow": {
"description": "UseClassicParameterFlow is a flag that switches the default behavior to use the classic\nparameter flow when creating a workspace. This only affects deployments with the experiment\n\"dynamic-parameters\" enabled. This setting will live for a period after the experiment is\nmade the default.\nAn \"opt-out\" is present in case the new feature breaks some existing templates.",
"type": "boolean"
},
"use_terraform_workspace_cache": {
"description": "UseTerraformWorkspaceCache allows optionally specifying whether to use cached\nterraform directories for workspaces created from this template. This field\nonly applies when the correct experiment is enabled. This field is subject to\nbeing removed in the future.",
"type": "boolean"
}
}
},
@@ -18101,6 +18173,14 @@
"description": "OwnerName is the username of the owner of the workspace.",
"type": "string"
},
"task_id": {
"description": "TaskID, if set, indicates that the workspace is relevant to the given codersdk.Task.",
"allOf": [
{
"$ref": "#/definitions/uuid.NullUUID"
}
]
},
"template_active_version_id": {
"type": "string",
"format": "uuid"
@@ -18855,11 +18935,6 @@
"codersdk.WorkspaceBuild": {
"type": "object",
"properties": {
"ai_task_sidebar_app_id": {
"description": "Deprecated: This field has been replaced with `TaskAppID`",
"type": "string",
"format": "uuid"
},
"build_number": {
"type": "integer"
},
@@ -18875,6 +18950,7 @@
"format": "date-time"
},
"has_ai_task": {
"description": "Deprecated: This field has been deprecated in favor of Task WorkspaceID.",
"type": "boolean"
},
"has_external_agent": {
@@ -18934,10 +19010,6 @@
}
]
},
"task_app_id": {
"type": "string",
"format": "uuid"
},
"template_version_id": {
"type": "string",
"format": "uuid"
+2 -2
View File
@@ -509,11 +509,11 @@ func (api *API) auditLogResourceLink(ctx context.Context, alog database.GetAudit
if err != nil {
return ""
}
workspace, err := api.Database.GetWorkspaceByID(ctx, task.WorkspaceID.UUID)
user, err := api.Database.GetUserByID(ctx, task.OwnerID)
if err != nil {
return ""
}
return fmt.Sprintf("/tasks/%s/%s", workspace.OwnerName, task.Name)
return fmt.Sprintf("/tasks/%s/%s", user.Username, task.ID)
default:
return ""
+172
View File
@@ -1764,3 +1764,175 @@ func TestExecutorAutostartSkipsWhenNoProvisionersAvailable(t *testing.T) {
assert.Len(t, stats.Transitions, 1, "should create builds when provisioners are available")
}
func TestExecutorTaskWorkspace(t *testing.T) {
t.Parallel()
createTaskTemplate := func(t *testing.T, client *codersdk.Client, orgID uuid.UUID, ctx context.Context, defaultTTL time.Duration) codersdk.Template {
t.Helper()
taskAppID := uuid.New()
version := coderdtest.CreateTemplateVersion(t, client, orgID, &echo.Responses{
Parse: echo.ParseComplete,
ProvisionPlan: []*proto.Response{
{
Type: &proto.Response_Plan{
Plan: &proto.PlanComplete{HasAiTasks: true},
},
},
},
ProvisionApply: []*proto.Response{
{
Type: &proto.Response_Apply{
Apply: &proto.ApplyComplete{
Resources: []*proto.Resource{
{
Agents: []*proto.Agent{
{
Id: uuid.NewString(),
Name: "dev",
Auth: &proto.Agent_Token{
Token: uuid.NewString(),
},
Apps: []*proto.App{
{
Id: taskAppID.String(),
Slug: "task-app",
},
},
},
},
},
},
AiTasks: []*proto.AITask{
{
AppId: taskAppID.String(),
},
},
},
},
},
},
})
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
template := coderdtest.CreateTemplate(t, client, orgID, version.ID)
if defaultTTL > 0 {
_, err := client.UpdateTemplateMeta(ctx, template.ID, codersdk.UpdateTemplateMeta{
DefaultTTLMillis: defaultTTL.Milliseconds(),
})
require.NoError(t, err)
}
return template
}
createTaskWorkspace := func(t *testing.T, client *codersdk.Client, template codersdk.Template, ctx context.Context, input string) codersdk.Workspace {
t.Helper()
exp := codersdk.NewExperimentalClient(client)
task, err := exp.CreateTask(ctx, "me", codersdk.CreateTaskRequest{
TemplateVersionID: template.ActiveVersionID,
Input: input,
})
require.NoError(t, err)
require.True(t, task.WorkspaceID.Valid, "task should have a workspace")
workspace, err := client.Workspace(ctx, task.WorkspaceID.UUID)
require.NoError(t, err)
coderdtest.AwaitWorkspaceBuildJobCompleted(t, client, workspace.LatestBuild.ID)
return workspace
}
t.Run("Autostart", func(t *testing.T) {
t.Parallel()
var (
ctx = testutil.Context(t, testutil.WaitShort)
sched = mustSchedule(t, "CRON_TZ=UTC 0 * * * *")
tickCh = make(chan time.Time)
statsCh = make(chan autobuild.Stats)
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
AutobuildTicker: tickCh,
IncludeProvisionerDaemon: true,
AutobuildStats: statsCh,
})
admin = coderdtest.CreateFirstUser(t, client)
)
// Given: A task workspace
template := createTaskTemplate(t, client, admin.OrganizationID, ctx, 0)
workspace := createTaskWorkspace(t, client, template, ctx, "test task for autostart")
// Given: The task workspace has an autostart schedule
err := client.UpdateWorkspaceAutostart(ctx, workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
Schedule: ptr.Ref(sched.String()),
})
require.NoError(t, err)
// Given: That the workspace is in a stopped state.
workspace = coderdtest.MustTransitionWorkspace(t, client, workspace.ID, codersdk.WorkspaceTransitionStart, codersdk.WorkspaceTransitionStop)
p, err := coderdtest.GetProvisionerForTags(db, time.Now(), workspace.OrganizationID, map[string]string{})
require.NoError(t, err)
// When: the autobuild executor ticks after the scheduled time
go func() {
tickTime := sched.Next(workspace.LatestBuild.CreatedAt)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
close(tickCh)
}()
// Then: We expect to see a start transition
stats := <-statsCh
require.Len(t, stats.Transitions, 1, "lifecycle executor should transition the task workspace")
assert.Contains(t, stats.Transitions, workspace.ID, "task workspace should be in transitions")
assert.Equal(t, database.WorkspaceTransitionStart, stats.Transitions[workspace.ID], "should autostart the workspace")
require.Empty(t, stats.Errors, "should have no errors when managing task workspaces")
})
t.Run("Autostop", func(t *testing.T) {
t.Parallel()
var (
ctx = testutil.Context(t, testutil.WaitShort)
tickCh = make(chan time.Time)
statsCh = make(chan autobuild.Stats)
client, db = coderdtest.NewWithDatabase(t, &coderdtest.Options{
AutobuildTicker: tickCh,
IncludeProvisionerDaemon: true,
AutobuildStats: statsCh,
})
admin = coderdtest.CreateFirstUser(t, client)
)
// Given: A task workspace with an 8 hour deadline
template := createTaskTemplate(t, client, admin.OrganizationID, ctx, 8*time.Hour)
workspace := createTaskWorkspace(t, client, template, ctx, "test task for autostop")
// Given: The workspace is currently running
workspace = coderdtest.MustWorkspace(t, client, workspace.ID)
require.Equal(t, codersdk.WorkspaceTransitionStart, workspace.LatestBuild.Transition)
require.NotZero(t, workspace.LatestBuild.Deadline, "workspace should have a deadline for autostop")
p, err := coderdtest.GetProvisionerForTags(db, time.Now(), workspace.OrganizationID, map[string]string{})
require.NoError(t, err)
// When: the autobuild executor ticks after the deadline
go func() {
tickTime := workspace.LatestBuild.Deadline.Time.Add(time.Minute)
coderdtest.UpdateProvisionerLastSeenAt(t, db, p.ID, tickTime)
tickCh <- tickTime
close(tickCh)
}()
// Then: We expect to see a stop transition
stats := <-statsCh
require.Len(t, stats.Transitions, 1, "lifecycle executor should transition the task workspace")
assert.Contains(t, stats.Transitions, workspace.ID, "task workspace should be in transitions")
assert.Equal(t, database.WorkspaceTransitionStop, stats.Transitions[workspace.ID], "should autostop the workspace")
require.Empty(t, stats.Errors, "should have no errors when managing task workspaces")
})
}
+3 -4
View File
@@ -610,6 +610,7 @@ func New(options *Options) *API {
dbRolluper: options.DatabaseRolluper,
}
api.WorkspaceAppsProvider = workspaceapps.NewDBTokenProvider(
ctx,
options.Logger.Named("workspaceapps"),
options.AccessURL,
options.Authorizer,
@@ -1021,10 +1022,7 @@ func New(options *Options) *API {
apiRateLimiter,
httpmw.ReportCLITelemetry(api.Logger, options.Telemetry),
)
r.Route("/aitasks", func(r chi.Router) {
r.Use(apiKeyMiddleware)
r.Get("/prompts", api.aiTasksPrompts)
})
r.Route("/tasks", func(r chi.Router) {
r.Use(apiKeyMiddleware)
@@ -2002,6 +2000,7 @@ func (api *API) CreateInMemoryTaggedProvisionerDaemon(dialCtx context.Context, n
api.NotificationsEnqueuer,
&api.PrebuildsReconciler,
api.ProvisionerdServerMetrics,
api.Experiments,
)
if err != nil {
return nil, err
+1 -1
View File
@@ -1604,7 +1604,7 @@ func (nopcloser) Close() error { return nil }
// SDKError coerces err into an SDK error.
func SDKError(t testing.TB, err error) *codersdk.Error {
var cerr *codersdk.Error
require.True(t, errors.As(err, &cerr), "should be SDK error, got %w", err)
require.True(t, errors.As(err, &cerr), "should be SDK error, got %s", err)
return cerr
}
+10 -11
View File
@@ -6,15 +6,14 @@ type CheckConstraint string
// CheckConstraint enums.
const (
CheckAPIKeysAllowListNotEmpty CheckConstraint = "api_keys_allow_list_not_empty" // api_keys
CheckOneTimePasscodeSet CheckConstraint = "one_time_passcode_set" // users
CheckUsersUsernameMinLength CheckConstraint = "users_username_min_length" // users
CheckMaxProvisionerLogsLength CheckConstraint = "max_provisioner_logs_length" // provisioner_jobs
CheckMaxLogsLength CheckConstraint = "max_logs_length" // workspace_agents
CheckSubsystemsNotNone CheckConstraint = "subsystems_not_none" // workspace_agents
CheckWorkspaceBuildsAiTaskSidebarAppIDRequired CheckConstraint = "workspace_builds_ai_task_sidebar_app_id_required" // workspace_builds
CheckWorkspaceBuildsDeadlineBelowMaxDeadline CheckConstraint = "workspace_builds_deadline_below_max_deadline" // workspace_builds
CheckTelemetryLockEventTypeConstraint CheckConstraint = "telemetry_lock_event_type_constraint" // telemetry_locks
CheckValidationMonotonicOrder CheckConstraint = "validation_monotonic_order" // template_version_parameters
CheckUsageEventTypeCheck CheckConstraint = "usage_event_type_check" // usage_events
CheckAPIKeysAllowListNotEmpty CheckConstraint = "api_keys_allow_list_not_empty" // api_keys
CheckOneTimePasscodeSet CheckConstraint = "one_time_passcode_set" // users
CheckUsersUsernameMinLength CheckConstraint = "users_username_min_length" // users
CheckMaxProvisionerLogsLength CheckConstraint = "max_provisioner_logs_length" // provisioner_jobs
CheckMaxLogsLength CheckConstraint = "max_logs_length" // workspace_agents
CheckSubsystemsNotNone CheckConstraint = "subsystems_not_none" // workspace_agents
CheckWorkspaceBuildsDeadlineBelowMaxDeadline CheckConstraint = "workspace_builds_deadline_below_max_deadline" // workspace_builds
CheckTelemetryLockEventTypeConstraint CheckConstraint = "telemetry_lock_event_type_constraint" // telemetry_locks
CheckValidationMonotonicOrder CheckConstraint = "validation_monotonic_order" // template_version_parameters
CheckUsageEventTypeCheck CheckConstraint = "usage_event_type_check" // usage_events
)
+15
View File
@@ -974,6 +974,9 @@ func AIBridgeInterception(interception database.AIBridgeInterception, initiator
UserPrompts: sdkUserPrompts,
ToolUsages: sdkToolUsages,
}
if interception.APIKeyID.Valid {
intc.APIKeyID = &interception.APIKeyID.String
}
if interception.EndedAt.Valid {
intc.EndedAt = &interception.EndedAt.Time
}
@@ -1018,6 +1021,18 @@ func AIBridgeToolUsage(usage database.AIBridgeToolUsage) codersdk.AIBridgeToolUs
}
}
func InvalidatedPresets(invalidatedPresets []database.UpdatePresetsLastInvalidatedAtRow) []codersdk.InvalidatedPreset {
var presets []codersdk.InvalidatedPreset
for _, p := range invalidatedPresets {
presets = append(presets, codersdk.InvalidatedPreset{
TemplateName: p.TemplateName,
TemplateVersionName: p.TemplateVersionName,
PresetName: p.TemplateVersionPresetName,
})
}
return presets
}
func jsonOrEmptyMap(rawMessage pqtype.NullRawMessage) map[string]any {
var m map[string]any
if !rawMessage.Valid {
+30 -4
View File
@@ -219,8 +219,8 @@ var (
rbac.ResourceUser.Type: {policy.ActionRead, policy.ActionReadPersonal, policy.ActionUpdatePersonal},
rbac.ResourceWorkspaceDormant.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStop},
rbac.ResourceWorkspace.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStart, policy.ActionWorkspaceStop, policy.ActionCreateAgent},
// Provisionerd needs to read and update tasks associated with workspaces.
rbac.ResourceTask.Type: {policy.ActionRead, policy.ActionUpdate},
// Provisionerd needs to read, update, and delete tasks associated with workspaces.
rbac.ResourceTask.Type: {policy.ActionRead, policy.ActionUpdate, policy.ActionDelete},
rbac.ResourceApiKey.Type: {policy.WildcardSymbol},
// When org scoped provisioner credentials are implemented,
// this can be reduced to read a specific org.
@@ -254,6 +254,7 @@ var (
rbac.ResourceFile.Type: {policy.ActionRead}, // Required to read terraform files
rbac.ResourceNotificationMessage.Type: {policy.ActionCreate, policy.ActionRead},
rbac.ResourceSystem.Type: {policy.WildcardSymbol},
rbac.ResourceTask.Type: {policy.ActionRead, policy.ActionUpdate},
rbac.ResourceTemplate.Type: {policy.ActionRead, policy.ActionUpdate},
rbac.ResourceUser.Type: {policy.ActionRead},
rbac.ResourceWorkspace.Type: {policy.ActionDelete, policy.ActionRead, policy.ActionUpdate, policy.ActionWorkspaceStart, policy.ActionWorkspaceStop},
@@ -2648,6 +2649,13 @@ func (q *querier) GetOrganizationsByUserID(ctx context.Context, userID database.
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetOrganizationsByUserID)(ctx, userID)
}
func (q *querier) GetOrganizationsWithPrebuildStatus(ctx context.Context, arg database.GetOrganizationsWithPrebuildStatusParams) ([]database.GetOrganizationsWithPrebuildStatusRow, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceOrganization.All()); err != nil {
return nil, err
}
return q.db.GetOrganizationsWithPrebuildStatus(ctx, arg)
}
func (q *querier) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUID) ([]database.ParameterSchema, error) {
version, err := q.db.GetTemplateVersionByJobID(ctx, jobID)
if err != nil {
@@ -2981,6 +2989,10 @@ func (q *querier) GetTaskByID(ctx context.Context, id uuid.UUID) (database.Task,
return fetch(q.log, q.auth, q.db.GetTaskByID)(ctx, id)
}
func (q *querier) GetTaskByOwnerIDAndName(ctx context.Context, arg database.GetTaskByOwnerIDAndNameParams) (database.Task, error) {
return fetch(q.log, q.auth, q.db.GetTaskByOwnerIDAndName)(ctx, arg)
}
func (q *querier) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (database.Task, error) {
return fetch(q.log, q.auth, q.db.GetTaskByWorkspaceID)(ctx, workspaceID)
}
@@ -4933,10 +4945,10 @@ func (q *querier) UpdateOrganizationDeletedByID(ctx context.Context, arg databas
return deleteQ(q.log, q.auth, q.db.GetOrganizationByID, deleteF)(ctx, arg.ID)
}
func (q *querier) UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg database.UpdatePrebuildProvisionerJobWithCancelParams) ([]uuid.UUID, error) {
func (q *querier) UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg database.UpdatePrebuildProvisionerJobWithCancelParams) ([]database.UpdatePrebuildProvisionerJobWithCancelRow, error) {
// Prebuild operation for canceling pending prebuild jobs from non-active template versions
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourcePrebuiltWorkspace); err != nil {
return []uuid.UUID{}, err
return []database.UpdatePrebuildProvisionerJobWithCancelRow{}, err
}
return q.db.UpdatePrebuildProvisionerJobWithCancel(ctx, arg)
}
@@ -4960,6 +4972,20 @@ func (q *querier) UpdatePresetPrebuildStatus(ctx context.Context, arg database.U
return q.db.UpdatePresetPrebuildStatus(ctx, arg)
}
func (q *querier) UpdatePresetsLastInvalidatedAt(ctx context.Context, arg database.UpdatePresetsLastInvalidatedAtParams) ([]database.UpdatePresetsLastInvalidatedAtRow, error) {
// Fetch template to check authorization
template, err := q.db.GetTemplateByID(ctx, arg.TemplateID)
if err != nil {
return nil, err
}
if err := q.authorizeContext(ctx, policy.ActionUpdate, template); err != nil {
return nil, err
}
return q.db.UpdatePresetsLastInvalidatedAt(ctx, arg)
}
func (q *querier) UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg database.UpdateProvisionerDaemonLastSeenAtParams) error {
if err := q.authorizeContext(ctx, policy.ActionUpdate, rbac.ResourceProvisionerDaemon); err != nil {
return err
+33 -5
View File
@@ -646,10 +646,13 @@ func (s *MethodTestSuite) TestProvisionerJob() {
PresetID: uuid.NullUUID{UUID: uuid.New(), Valid: true},
Now: dbtime.Now(),
}
jobIDs := []uuid.UUID{uuid.New(), uuid.New()}
canceledJobs := []database.UpdatePrebuildProvisionerJobWithCancelRow{
{ID: uuid.New(), WorkspaceID: uuid.New(), TemplateID: uuid.New(), TemplateVersionPresetID: uuid.NullUUID{UUID: uuid.New(), Valid: true}},
{ID: uuid.New(), WorkspaceID: uuid.New(), TemplateID: uuid.New(), TemplateVersionPresetID: uuid.NullUUID{UUID: uuid.New(), Valid: true}},
}
dbm.EXPECT().UpdatePrebuildProvisionerJobWithCancel(gomock.Any(), arg).Return(jobIDs, nil).AnyTimes()
check.Args(arg).Asserts(rbac.ResourcePrebuiltWorkspace, policy.ActionUpdate).Returns(jobIDs)
dbm.EXPECT().UpdatePrebuildProvisionerJobWithCancel(gomock.Any(), arg).Return(canceledJobs, nil).AnyTimes()
check.Args(arg).Asserts(rbac.ResourcePrebuiltWorkspace, policy.ActionUpdate).Returns(canceledJobs)
}))
s.Run("GetProvisionerJobsByIDs", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
org := testutil.Fake(s.T(), faker, database.Organization{})
@@ -1312,6 +1315,13 @@ func (s *MethodTestSuite) TestTemplate() {
dbm.EXPECT().UpsertTemplateUsageStats(gomock.Any()).Return(nil).AnyTimes()
check.Asserts(rbac.ResourceSystem, policy.ActionUpdate)
}))
s.Run("UpdatePresetsLastInvalidatedAt", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
t1 := testutil.Fake(s.T(), faker, database.Template{})
arg := database.UpdatePresetsLastInvalidatedAtParams{LastInvalidatedAt: sql.NullTime{Valid: true, Time: dbtime.Now()}, TemplateID: t1.ID}
dbm.EXPECT().GetTemplateByID(gomock.Any(), t1.ID).Return(t1, nil).AnyTimes()
dbm.EXPECT().UpdatePresetsLastInvalidatedAt(gomock.Any(), arg).Return([]database.UpdatePresetsLastInvalidatedAtRow{}, nil).AnyTimes()
check.Args(arg).Asserts(t1, policy.ActionUpdate)
}))
}
func (s *MethodTestSuite) TestUser() {
@@ -2158,7 +2168,7 @@ func (s *MethodTestSuite) TestWorkspace() {
})
res := testutil.Fake(s.T(), faker, database.WorkspaceResource{JobID: b.JobID})
agt := testutil.Fake(s.T(), faker, database.WorkspaceAgent{ResourceID: res.ID})
app := testutil.Fake(s.T(), faker, database.WorkspaceApp{AgentID: agt.ID})
_ = testutil.Fake(s.T(), faker, database.WorkspaceApp{AgentID: agt.ID})
dbm.EXPECT().GetWorkspaceByID(gomock.Any(), w.ID).Return(w, nil).AnyTimes()
dbm.EXPECT().GetWorkspaceBuildByID(gomock.Any(), b.ID).Return(b, nil).AnyTimes()
@@ -2167,7 +2177,6 @@ func (s *MethodTestSuite) TestWorkspace() {
ID: b.ID,
HasAITask: sql.NullBool{Bool: true, Valid: true},
HasExternalAgent: sql.NullBool{Bool: true, Valid: true},
SidebarAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
UpdatedAt: b.UpdatedAt,
}).Asserts(w, policy.ActionUpdate)
}))
@@ -2372,6 +2381,17 @@ func (s *MethodTestSuite) TestTasks() {
dbm.EXPECT().GetTaskByID(gomock.Any(), task.ID).Return(task, nil).AnyTimes()
check.Args(task.ID).Asserts(task, policy.ActionRead).Returns(task)
}))
s.Run("GetTaskByOwnerIDAndName", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
task := testutil.Fake(s.T(), faker, database.Task{})
dbm.EXPECT().GetTaskByOwnerIDAndName(gomock.Any(), database.GetTaskByOwnerIDAndNameParams{
OwnerID: task.OwnerID,
Name: task.Name,
}).Return(task, nil).AnyTimes()
check.Args(database.GetTaskByOwnerIDAndNameParams{
OwnerID: task.OwnerID,
Name: task.Name,
}).Asserts(task, policy.ActionRead).Returns(task)
}))
s.Run("DeleteTask", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
task := testutil.Fake(s.T(), faker, database.Task{})
arg := database.DeleteTaskParams{
@@ -3756,6 +3776,14 @@ func (s *MethodTestSuite) TestPrebuilds() {
dbm.EXPECT().GetPrebuildMetrics(gomock.Any()).Return([]database.GetPrebuildMetricsRow{}, nil).AnyTimes()
check.Args().Asserts(rbac.ResourceWorkspace.All(), policy.ActionRead)
}))
s.Run("GetOrganizationsWithPrebuildStatus", s.Mocked(func(dbm *dbmock.MockStore, faker *gofakeit.Faker, check *expects) {
arg := database.GetOrganizationsWithPrebuildStatusParams{
UserID: uuid.New(),
GroupName: "test",
}
dbm.EXPECT().GetOrganizationsWithPrebuildStatus(gomock.Any(), arg).Return([]database.GetOrganizationsWithPrebuildStatusRow{}, nil).AnyTimes()
check.Args(arg).Asserts(rbac.ResourceOrganization.All(), policy.ActionRead)
}))
s.Run("GetPrebuildsSettings", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
dbm.EXPECT().GetPrebuildsSettings(gomock.Any()).Return("{}", nil).AnyTimes()
check.Args().Asserts()
+13 -4
View File
@@ -189,7 +189,6 @@ func (b WorkspaceBuildBuilder) doInTX() WorkspaceResponse {
Bool: true,
Valid: true,
}
b.seed.AITaskSidebarAppID = uuid.NullUUID{UUID: b.taskAppID, Valid: true}
}
resp := WorkspaceResponse{
@@ -362,12 +361,20 @@ func (b WorkspaceBuildBuilder) doInTX() WorkspaceResponse {
require.Fail(b.t, "task app not configured but workspace is a task workspace")
}
app := mustWorkspaceAppByWorkspaceAndBuildAndAppID(ownerCtx, b.t, b.db, resp.Workspace.ID, resp.Build.BuildNumber, b.taskAppID)
workspaceAgentID := uuid.NullUUID{}
workspaceAppID := uuid.NullUUID{}
// Workspace agent and app are only properly set upon job completion
if b.jobStatus != database.ProvisionerJobStatusPending && b.jobStatus != database.ProvisionerJobStatusRunning {
app := mustWorkspaceAppByWorkspaceAndBuildAndAppID(ownerCtx, b.t, b.db, resp.Workspace.ID, resp.Build.BuildNumber, b.taskAppID)
workspaceAgentID = uuid.NullUUID{UUID: app.AgentID, Valid: true}
workspaceAppID = uuid.NullUUID{UUID: app.ID, Valid: true}
}
_, err = b.db.UpsertTaskWorkspaceApp(ownerCtx, database.UpsertTaskWorkspaceAppParams{
TaskID: task.ID,
WorkspaceBuildNumber: resp.Build.BuildNumber,
WorkspaceAgentID: uuid.NullUUID{UUID: app.AgentID, Valid: true},
WorkspaceAppID: uuid.NullUUID{UUID: app.ID, Valid: true},
WorkspaceAgentID: workspaceAgentID,
WorkspaceAppID: workspaceAppID,
})
require.NoError(b.t, err, "upsert task workspace app")
b.logger.Debug(context.Background(), "linked task to workspace build",
@@ -606,6 +613,7 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
IsDefault: false,
Description: preset.Description,
Icon: preset.Icon,
LastInvalidatedAt: preset.LastInvalidatedAt,
})
t.logger.Debug(context.Background(), "added preset",
slog.F("preset_id", prst.ID),
@@ -623,6 +631,7 @@ func (t TemplateVersionBuilder) Do() TemplateVersionResponse {
}
payload, err := json.Marshal(provisionerdserver.TemplateVersionImportJob{
TemplateID: t.seed.TemplateID,
TemplateVersionID: t.seed.ID,
})
require.NoError(t.t, err)
+2 -2
View File
@@ -451,7 +451,6 @@ func WorkspaceBuild(t testing.TB, db database.Store, orig database.WorkspaceBuil
buildID := takeFirst(orig.ID, uuid.New())
jobID := takeFirst(orig.JobID, uuid.New())
hasAITask := takeFirst(orig.HasAITask, sql.NullBool{})
sidebarAppID := takeFirst(orig.AITaskSidebarAppID, uuid.NullUUID{})
hasExternalAgent := takeFirst(orig.HasExternalAgent, sql.NullBool{})
var build database.WorkspaceBuild
err := db.InTx(func(db database.Store) error {
@@ -491,7 +490,6 @@ func WorkspaceBuild(t testing.TB, db database.Store, orig database.WorkspaceBuil
ID: buildID,
HasAITask: hasAITask,
HasExternalAgent: hasExternalAgent,
SidebarAppID: sidebarAppID,
UpdatedAt: dbtime.Now(),
}))
}
@@ -1430,6 +1428,7 @@ func Preset(t testing.TB, db database.Store, seed database.InsertPresetParams) d
IsDefault: seed.IsDefault,
Description: seed.Description,
Icon: seed.Icon,
LastInvalidatedAt: seed.LastInvalidatedAt,
})
require.NoError(t, err, "insert preset")
return preset
@@ -1498,6 +1497,7 @@ func ClaimPrebuild(
func AIBridgeInterception(t testing.TB, db database.Store, seed database.InsertAIBridgeInterceptionParams, endedAt *time.Time) database.AIBridgeInterception {
interception, err := db.InsertAIBridgeInterception(genCtx, database.InsertAIBridgeInterceptionParams{
ID: takeFirst(seed.ID, uuid.New()),
APIKeyID: seed.APIKeyID,
InitiatorID: takeFirst(seed.InitiatorID, uuid.New()),
Provider: takeFirst(seed.Provider, "provider"),
Model: takeFirst(seed.Model, "model"),
+22 -1
View File
@@ -1243,6 +1243,13 @@ func (m queryMetricsStore) GetOrganizationsByUserID(ctx context.Context, userID
return organizations, err
}
func (m queryMetricsStore) GetOrganizationsWithPrebuildStatus(ctx context.Context, arg database.GetOrganizationsWithPrebuildStatusParams) ([]database.GetOrganizationsWithPrebuildStatusRow, error) {
start := time.Now()
r0, r1 := m.s.GetOrganizationsWithPrebuildStatus(ctx, arg)
m.queryLatencies.WithLabelValues("GetOrganizationsWithPrebuildStatus").Observe(time.Since(start).Seconds())
return r0, r1
}
func (m queryMetricsStore) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUID) ([]database.ParameterSchema, error) {
start := time.Now()
schemas, err := m.s.GetParameterSchemasByJobID(ctx, jobID)
@@ -1523,6 +1530,13 @@ func (m queryMetricsStore) GetTaskByID(ctx context.Context, id uuid.UUID) (datab
return r0, r1
}
func (m queryMetricsStore) GetTaskByOwnerIDAndName(ctx context.Context, arg database.GetTaskByOwnerIDAndNameParams) (database.Task, error) {
start := time.Now()
r0, r1 := m.s.GetTaskByOwnerIDAndName(ctx, arg)
m.queryLatencies.WithLabelValues("GetTaskByOwnerIDAndName").Observe(time.Since(start).Seconds())
return r0, r1
}
func (m queryMetricsStore) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (database.Task, error) {
start := time.Now()
r0, r1 := m.s.GetTaskByWorkspaceID(ctx, workspaceID)
@@ -3042,7 +3056,7 @@ func (m queryMetricsStore) UpdateOrganizationDeletedByID(ctx context.Context, ar
return r0
}
func (m queryMetricsStore) UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg database.UpdatePrebuildProvisionerJobWithCancelParams) ([]uuid.UUID, error) {
func (m queryMetricsStore) UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg database.UpdatePrebuildProvisionerJobWithCancelParams) ([]database.UpdatePrebuildProvisionerJobWithCancelRow, error) {
start := time.Now()
r0, r1 := m.s.UpdatePrebuildProvisionerJobWithCancel(ctx, arg)
m.queryLatencies.WithLabelValues("UpdatePrebuildProvisionerJobWithCancel").Observe(time.Since(start).Seconds())
@@ -3056,6 +3070,13 @@ func (m queryMetricsStore) UpdatePresetPrebuildStatus(ctx context.Context, arg d
return r0
}
func (m queryMetricsStore) UpdatePresetsLastInvalidatedAt(ctx context.Context, arg database.UpdatePresetsLastInvalidatedAtParams) ([]database.UpdatePresetsLastInvalidatedAtRow, error) {
start := time.Now()
r0, r1 := m.s.UpdatePresetsLastInvalidatedAt(ctx, arg)
m.queryLatencies.WithLabelValues("UpdatePresetsLastInvalidatedAt").Observe(time.Since(start).Seconds())
return r0, r1
}
func (m queryMetricsStore) UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg database.UpdateProvisionerDaemonLastSeenAtParams) error {
start := time.Now()
r0 := m.s.UpdateProvisionerDaemonLastSeenAt(ctx, arg)
+47 -2
View File
@@ -2622,6 +2622,21 @@ func (mr *MockStoreMockRecorder) GetOrganizationsByUserID(ctx, arg any) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOrganizationsByUserID", reflect.TypeOf((*MockStore)(nil).GetOrganizationsByUserID), ctx, arg)
}
// GetOrganizationsWithPrebuildStatus mocks base method.
func (m *MockStore) GetOrganizationsWithPrebuildStatus(ctx context.Context, arg database.GetOrganizationsWithPrebuildStatusParams) ([]database.GetOrganizationsWithPrebuildStatusRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetOrganizationsWithPrebuildStatus", ctx, arg)
ret0, _ := ret[0].([]database.GetOrganizationsWithPrebuildStatusRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetOrganizationsWithPrebuildStatus indicates an expected call of GetOrganizationsWithPrebuildStatus.
func (mr *MockStoreMockRecorder) GetOrganizationsWithPrebuildStatus(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOrganizationsWithPrebuildStatus", reflect.TypeOf((*MockStore)(nil).GetOrganizationsWithPrebuildStatus), ctx, arg)
}
// GetParameterSchemasByJobID mocks base method.
func (m *MockStore) GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUID) ([]database.ParameterSchema, error) {
m.ctrl.T.Helper()
@@ -3222,6 +3237,21 @@ func (mr *MockStoreMockRecorder) GetTaskByID(ctx, id any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTaskByID", reflect.TypeOf((*MockStore)(nil).GetTaskByID), ctx, id)
}
// GetTaskByOwnerIDAndName mocks base method.
func (m *MockStore) GetTaskByOwnerIDAndName(ctx context.Context, arg database.GetTaskByOwnerIDAndNameParams) (database.Task, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetTaskByOwnerIDAndName", ctx, arg)
ret0, _ := ret[0].(database.Task)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetTaskByOwnerIDAndName indicates an expected call of GetTaskByOwnerIDAndName.
func (mr *MockStoreMockRecorder) GetTaskByOwnerIDAndName(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTaskByOwnerIDAndName", reflect.TypeOf((*MockStore)(nil).GetTaskByOwnerIDAndName), ctx, arg)
}
// GetTaskByWorkspaceID mocks base method.
func (m *MockStore) GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (database.Task, error) {
m.ctrl.T.Helper()
@@ -6540,10 +6570,10 @@ func (mr *MockStoreMockRecorder) UpdateOrganizationDeletedByID(ctx, arg any) *go
}
// UpdatePrebuildProvisionerJobWithCancel mocks base method.
func (m *MockStore) UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg database.UpdatePrebuildProvisionerJobWithCancelParams) ([]uuid.UUID, error) {
func (m *MockStore) UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg database.UpdatePrebuildProvisionerJobWithCancelParams) ([]database.UpdatePrebuildProvisionerJobWithCancelRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdatePrebuildProvisionerJobWithCancel", ctx, arg)
ret0, _ := ret[0].([]uuid.UUID)
ret0, _ := ret[0].([]database.UpdatePrebuildProvisionerJobWithCancelRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
@@ -6568,6 +6598,21 @@ func (mr *MockStoreMockRecorder) UpdatePresetPrebuildStatus(ctx, arg any) *gomoc
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePresetPrebuildStatus", reflect.TypeOf((*MockStore)(nil).UpdatePresetPrebuildStatus), ctx, arg)
}
// UpdatePresetsLastInvalidatedAt mocks base method.
func (m *MockStore) UpdatePresetsLastInvalidatedAt(ctx context.Context, arg database.UpdatePresetsLastInvalidatedAtParams) ([]database.UpdatePresetsLastInvalidatedAtRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdatePresetsLastInvalidatedAt", ctx, arg)
ret0, _ := ret[0].([]database.UpdatePresetsLastInvalidatedAtRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// UpdatePresetsLastInvalidatedAt indicates an expected call of UpdatePresetsLastInvalidatedAt.
func (mr *MockStoreMockRecorder) UpdatePresetsLastInvalidatedAt(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdatePresetsLastInvalidatedAt", reflect.TypeOf((*MockStore)(nil).UpdatePresetsLastInvalidatedAt), ctx, arg)
}
// UpdateProvisionerDaemonLastSeenAt mocks base method.
func (m *MockStore) UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg database.UpdateProvisionerDaemonLastSeenAtParams) error {
m.ctrl.T.Helper()
+50 -40
View File
@@ -1056,7 +1056,8 @@ CREATE TABLE aibridge_interceptions (
model text NOT NULL,
started_at timestamp with time zone NOT NULL,
metadata jsonb,
ended_at timestamp with time zone
ended_at timestamp with time zone,
api_key_id text
);
COMMENT ON TABLE aibridge_interceptions IS 'Audit log of requests intercepted by AI Bridge';
@@ -1948,9 +1949,7 @@ CREATE TABLE workspace_builds (
max_deadline timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL,
template_version_preset_id uuid,
has_ai_task boolean,
ai_task_sidebar_app_id uuid,
has_external_agent boolean,
CONSTRAINT workspace_builds_ai_task_sidebar_app_id_required CHECK (((((has_ai_task IS NULL) OR (has_ai_task = false)) AND (ai_task_sidebar_app_id IS NULL)) OR ((has_ai_task = true) AND (ai_task_sidebar_app_id IS NOT NULL)))),
CONSTRAINT workspace_builds_deadline_below_max_deadline CHECK ((((deadline <> '0001-01-01 00:00:00+00'::timestamp with time zone) AND (deadline <= max_deadline)) OR (max_deadline = '0001-01-01 00:00:00+00'::timestamp with time zone)))
);
@@ -1966,32 +1965,21 @@ CREATE VIEW tasks_with_status AS
tasks.created_at,
tasks.deleted_at,
CASE
WHEN ((tasks.workspace_id IS NULL) OR (latest_build.job_status IS NULL)) THEN 'pending'::task_status
WHEN (latest_build.job_status = 'failed'::provisioner_job_status) THEN 'error'::task_status
WHEN ((latest_build.transition = ANY (ARRAY['stop'::workspace_transition, 'delete'::workspace_transition])) AND (latest_build.job_status = 'succeeded'::provisioner_job_status)) THEN 'paused'::task_status
WHEN ((latest_build.transition = 'start'::workspace_transition) AND (latest_build.job_status = 'pending'::provisioner_job_status)) THEN 'initializing'::task_status
WHEN ((latest_build.transition = 'start'::workspace_transition) AND (latest_build.job_status = ANY (ARRAY['running'::provisioner_job_status, 'succeeded'::provisioner_job_status]))) THEN
CASE
WHEN agent_status."none" THEN 'initializing'::task_status
WHEN agent_status.connecting THEN 'initializing'::task_status
WHEN agent_status.connected THEN
CASE
WHEN app_status.any_unhealthy THEN 'error'::task_status
WHEN app_status.any_initializing THEN 'initializing'::task_status
WHEN app_status.all_healthy_or_disabled THEN 'active'::task_status
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
WHEN (tasks.workspace_id IS NULL) THEN 'pending'::task_status
WHEN (build_status.status <> 'active'::task_status) THEN build_status.status
WHEN (agent_status.status <> 'active'::task_status) THEN agent_status.status
ELSE app_status.status
END AS status,
jsonb_build_object('build', jsonb_build_object('transition', latest_build_raw.transition, 'job_status', latest_build_raw.job_status, 'computed', build_status.status), 'agent', jsonb_build_object('lifecycle_state', agent_raw.lifecycle_state, 'computed', agent_status.status), 'app', jsonb_build_object('health', app_raw.health, 'computed', app_status.status)) AS status_debug,
task_app.workspace_build_number,
task_app.workspace_agent_id,
task_app.workspace_app_id,
agent_raw.lifecycle_state AS workspace_agent_lifecycle_state,
app_raw.health AS workspace_app_health,
task_owner.owner_username,
task_owner.owner_name,
task_owner.owner_avatar_url
FROM (((((tasks
FROM ((((((((tasks
CROSS JOIN LATERAL ( SELECT vu.username AS owner_username,
vu.name AS owner_name,
vu.avatar_url AS owner_avatar_url
@@ -2009,17 +1997,36 @@ CREATE VIEW tasks_with_status AS
workspace_build.job_id
FROM (workspace_builds workspace_build
JOIN provisioner_jobs provisioner_job ON ((provisioner_job.id = workspace_build.job_id)))
WHERE ((workspace_build.workspace_id = tasks.workspace_id) AND (workspace_build.build_number = task_app.workspace_build_number))) latest_build ON (true))
CROSS JOIN LATERAL ( SELECT (count(*) = 0) AS "none",
bool_or((workspace_agent.lifecycle_state = ANY (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state]))) AS connecting,
bool_and((workspace_agent.lifecycle_state = 'ready'::workspace_agent_lifecycle_state)) AS connected
WHERE ((workspace_build.workspace_id = tasks.workspace_id) AND (workspace_build.build_number = task_app.workspace_build_number))) latest_build_raw ON (true))
LEFT JOIN LATERAL ( SELECT workspace_agent.lifecycle_state
FROM workspace_agents workspace_agent
WHERE (workspace_agent.id = task_app.workspace_agent_id)) agent_status)
CROSS JOIN LATERAL ( SELECT bool_or((workspace_app.health = 'unhealthy'::workspace_app_health)) AS any_unhealthy,
bool_or((workspace_app.health = 'initializing'::workspace_app_health)) AS any_initializing,
bool_and((workspace_app.health = ANY (ARRAY['healthy'::workspace_app_health, 'disabled'::workspace_app_health]))) AS all_healthy_or_disabled
WHERE (workspace_agent.id = task_app.workspace_agent_id)) agent_raw ON (true))
LEFT JOIN LATERAL ( SELECT workspace_app.health
FROM workspace_apps workspace_app
WHERE (workspace_app.id = task_app.workspace_app_id)) app_status)
WHERE (workspace_app.id = task_app.workspace_app_id)) app_raw ON (true))
CROSS JOIN LATERAL ( SELECT
CASE
WHEN (latest_build_raw.job_status IS NULL) THEN 'pending'::task_status
WHEN (latest_build_raw.job_status = ANY (ARRAY['failed'::provisioner_job_status, 'canceling'::provisioner_job_status, 'canceled'::provisioner_job_status])) THEN 'error'::task_status
WHEN ((latest_build_raw.transition = ANY (ARRAY['stop'::workspace_transition, 'delete'::workspace_transition])) AND (latest_build_raw.job_status = 'succeeded'::provisioner_job_status)) THEN 'paused'::task_status
WHEN ((latest_build_raw.transition = 'start'::workspace_transition) AND (latest_build_raw.job_status = 'pending'::provisioner_job_status)) THEN 'initializing'::task_status
WHEN ((latest_build_raw.transition = 'start'::workspace_transition) AND (latest_build_raw.job_status = ANY (ARRAY['running'::provisioner_job_status, 'succeeded'::provisioner_job_status]))) THEN 'active'::task_status
ELSE 'unknown'::task_status
END AS status) build_status)
CROSS JOIN LATERAL ( SELECT
CASE
WHEN ((agent_raw.lifecycle_state IS NULL) OR (agent_raw.lifecycle_state = ANY (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state]))) THEN 'initializing'::task_status
WHEN (agent_raw.lifecycle_state = ANY (ARRAY['ready'::workspace_agent_lifecycle_state, 'start_timeout'::workspace_agent_lifecycle_state, 'start_error'::workspace_agent_lifecycle_state])) THEN 'active'::task_status
WHEN (agent_raw.lifecycle_state <> ALL (ARRAY['created'::workspace_agent_lifecycle_state, 'starting'::workspace_agent_lifecycle_state, 'ready'::workspace_agent_lifecycle_state, 'start_timeout'::workspace_agent_lifecycle_state, 'start_error'::workspace_agent_lifecycle_state])) THEN 'unknown'::task_status
ELSE 'unknown'::task_status
END AS status) agent_status)
CROSS JOIN LATERAL ( SELECT
CASE
WHEN (app_raw.health = 'initializing'::workspace_app_health) THEN 'initializing'::task_status
WHEN (app_raw.health = 'unhealthy'::workspace_app_health) THEN 'error'::task_status
WHEN (app_raw.health = ANY (ARRAY['healthy'::workspace_app_health, 'disabled'::workspace_app_health])) THEN 'active'::task_status
ELSE 'unknown'::task_status
END AS status) app_status)
WHERE (tasks.deleted_at IS NULL);
CREATE TABLE telemetry_items (
@@ -2163,7 +2170,8 @@ CREATE TABLE template_version_presets (
scheduling_timezone text DEFAULT ''::text NOT NULL,
is_default boolean DEFAULT false NOT NULL,
description character varying(128) DEFAULT ''::character varying NOT NULL,
icon character varying(256) DEFAULT ''::character varying NOT NULL
icon character varying(256) DEFAULT ''::character varying NOT NULL,
last_invalidated_at timestamp with time zone
);
COMMENT ON COLUMN template_version_presets.description IS 'Short text describing the preset (max 128 characters).';
@@ -2287,7 +2295,8 @@ CREATE TABLE templates (
activity_bump bigint DEFAULT '3600000000000'::bigint NOT NULL,
max_port_sharing_level app_sharing_level DEFAULT 'owner'::app_sharing_level NOT NULL,
use_classic_parameter_flow boolean DEFAULT false NOT NULL,
cors_behavior cors_behavior DEFAULT 'simple'::cors_behavior NOT NULL
cors_behavior cors_behavior DEFAULT 'simple'::cors_behavior NOT NULL,
use_terraform_workspace_cache boolean DEFAULT false NOT NULL
);
COMMENT ON COLUMN templates.default_ttl IS 'The default duration for autostop for workspaces created from this template.';
@@ -2310,6 +2319,8 @@ COMMENT ON COLUMN templates.deprecated IS 'If set to a non empty string, the tem
COMMENT ON COLUMN templates.use_classic_parameter_flow IS 'Determines whether to default to the dynamic parameter creation flow for this template or continue using the legacy classic parameter creation flow.This is a template wide setting, the template admin can revert to the classic flow if there are any issues. An escape hatch is required, as workspace creation is a core workflow and cannot break. This column will be removed when the dynamic parameter creation flow is stable.';
COMMENT ON COLUMN templates.use_terraform_workspace_cache IS 'Determines whether to keep terraform directories cached between runs for workspaces created from this template. When enabled, this can significantly speed up the `terraform init` step at the cost of increased disk usage. This is an opt-in experience, as it prevents modules from being updated, and therefore is a behavioral difference from the default.';
CREATE VIEW template_with_names AS
SELECT templates.id,
templates.created_at,
@@ -2341,6 +2352,7 @@ CREATE VIEW template_with_names AS
templates.max_port_sharing_level,
templates.use_classic_parameter_flow,
templates.cors_behavior,
templates.use_terraform_workspace_cache,
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS created_by_username,
COALESCE(visible_users.name, ''::text) AS created_by_name,
@@ -2703,7 +2715,6 @@ CREATE VIEW workspace_build_with_user AS
workspace_builds.max_deadline,
workspace_builds.template_version_preset_id,
workspace_builds.has_ai_task,
workspace_builds.ai_task_sidebar_app_id,
workspace_builds.has_external_agent,
COALESCE(visible_users.avatar_url, ''::text) AS initiator_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS initiator_by_username,
@@ -2922,11 +2933,13 @@ CREATE VIEW workspaces_expanded AS
templates.name AS template_name,
templates.display_name AS template_display_name,
templates.icon AS template_icon,
templates.description AS template_description
FROM (((workspaces
templates.description AS template_description,
tasks.id AS task_id
FROM ((((workspaces
JOIN visible_users ON ((workspaces.owner_id = visible_users.id)))
JOIN organizations ON ((workspaces.organization_id = organizations.id)))
JOIN templates ON ((workspaces.template_id = templates.id)));
JOIN templates ON ((workspaces.template_id = templates.id)))
LEFT JOIN tasks ON ((workspaces.id = tasks.workspace_id)));
COMMENT ON VIEW workspaces_expanded IS 'Joins in the display name information such as username, avatar, and organization name.';
@@ -3802,9 +3815,6 @@ ALTER TABLE ONLY workspace_apps
ALTER TABLE ONLY workspace_build_parameters
ADD CONSTRAINT workspace_build_parameters_workspace_build_id_fkey FOREIGN KEY (workspace_build_id) REFERENCES workspace_builds(id) ON DELETE CASCADE;
ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_ai_task_sidebar_app_id_fkey FOREIGN KEY (ai_task_sidebar_app_id) REFERENCES workspace_apps(id);
ALTER TABLE ONLY workspace_builds
ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
@@ -94,7 +94,6 @@ const (
ForeignKeyWorkspaceAppStatusesWorkspaceID ForeignKeyConstraint = "workspace_app_statuses_workspace_id_fkey" // ALTER TABLE ONLY workspace_app_statuses ADD CONSTRAINT workspace_app_statuses_workspace_id_fkey FOREIGN KEY (workspace_id) REFERENCES workspaces(id);
ForeignKeyWorkspaceAppsAgentID ForeignKeyConstraint = "workspace_apps_agent_id_fkey" // ALTER TABLE ONLY workspace_apps ADD CONSTRAINT workspace_apps_agent_id_fkey FOREIGN KEY (agent_id) REFERENCES workspace_agents(id) ON DELETE CASCADE;
ForeignKeyWorkspaceBuildParametersWorkspaceBuildID ForeignKeyConstraint = "workspace_build_parameters_workspace_build_id_fkey" // ALTER TABLE ONLY workspace_build_parameters ADD CONSTRAINT workspace_build_parameters_workspace_build_id_fkey FOREIGN KEY (workspace_build_id) REFERENCES workspace_builds(id) ON DELETE CASCADE;
ForeignKeyWorkspaceBuildsAiTaskSidebarAppID ForeignKeyConstraint = "workspace_builds_ai_task_sidebar_app_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_ai_task_sidebar_app_id_fkey FOREIGN KEY (ai_task_sidebar_app_id) REFERENCES workspace_apps(id);
ForeignKeyWorkspaceBuildsJobID ForeignKeyConstraint = "workspace_builds_job_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_job_id_fkey FOREIGN KEY (job_id) REFERENCES provisioner_jobs(id) ON DELETE CASCADE;
ForeignKeyWorkspaceBuildsTemplateVersionID ForeignKeyConstraint = "workspace_builds_template_version_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_id_fkey FOREIGN KEY (template_version_id) REFERENCES template_versions(id) ON DELETE CASCADE;
ForeignKeyWorkspaceBuildsTemplateVersionPresetID ForeignKeyConstraint = "workspace_builds_template_version_preset_id_fkey" // ALTER TABLE ONLY workspace_builds ADD CONSTRAINT workspace_builds_template_version_preset_id_fkey FOREIGN KEY (template_version_preset_id) REFERENCES template_version_presets(id) ON DELETE SET NULL;
@@ -0,0 +1,39 @@
DROP VIEW workspaces_expanded;
-- Recreate the view from 000354_workspace_acl.up.sql
CREATE VIEW workspaces_expanded AS
SELECT workspaces.id,
workspaces.created_at,
workspaces.updated_at,
workspaces.owner_id,
workspaces.organization_id,
workspaces.template_id,
workspaces.deleted,
workspaces.name,
workspaces.autostart_schedule,
workspaces.ttl,
workspaces.last_used_at,
workspaces.dormant_at,
workspaces.deleting_at,
workspaces.automatic_updates,
workspaces.favorite,
workspaces.next_start_at,
workspaces.group_acl,
workspaces.user_acl,
visible_users.avatar_url AS owner_avatar_url,
visible_users.username AS owner_username,
visible_users.name AS owner_name,
organizations.name AS organization_name,
organizations.display_name AS organization_display_name,
organizations.icon AS organization_icon,
organizations.description AS organization_description,
templates.name AS template_name,
templates.display_name AS template_display_name,
templates.icon AS template_icon,
templates.description AS template_description
FROM (((workspaces
JOIN visible_users ON ((workspaces.owner_id = visible_users.id)))
JOIN organizations ON ((workspaces.organization_id = organizations.id)))
JOIN templates ON ((workspaces.template_id = templates.id)));
COMMENT ON VIEW workspaces_expanded IS 'Joins in the display name information such as username, avatar, and organization name.';
@@ -0,0 +1,42 @@
DROP VIEW workspaces_expanded;
-- Add nullable task_id to workspaces_expanded view
CREATE VIEW workspaces_expanded AS
SELECT workspaces.id,
workspaces.created_at,
workspaces.updated_at,
workspaces.owner_id,
workspaces.organization_id,
workspaces.template_id,
workspaces.deleted,
workspaces.name,
workspaces.autostart_schedule,
workspaces.ttl,
workspaces.last_used_at,
workspaces.dormant_at,
workspaces.deleting_at,
workspaces.automatic_updates,
workspaces.favorite,
workspaces.next_start_at,
workspaces.group_acl,
workspaces.user_acl,
visible_users.avatar_url AS owner_avatar_url,
visible_users.username AS owner_username,
visible_users.name AS owner_name,
organizations.name AS organization_name,
organizations.display_name AS organization_display_name,
organizations.icon AS organization_icon,
organizations.description AS organization_description,
templates.name AS template_name,
templates.display_name AS template_display_name,
templates.icon AS template_icon,
templates.description AS template_description,
tasks.id AS task_id
FROM ((((workspaces
JOIN visible_users ON ((workspaces.owner_id = visible_users.id)))
JOIN organizations ON ((workspaces.organization_id = organizations.id)))
JOIN templates ON ((workspaces.template_id = templates.id)))
LEFT JOIN tasks ON ((workspaces.id = tasks.workspace_id)));
COMMENT ON VIEW workspaces_expanded IS 'Joins in the display name information such as username, avatar, and organization name.';
@@ -0,0 +1,4 @@
-- WARNING: Restoring this constraint after running a newer version of coderd
-- and using tasks is bound to break this constraint.
ALTER TABLE workspace_builds
ADD CONSTRAINT workspace_builds_ai_task_sidebar_app_id_required CHECK (((((has_ai_task IS NULL) OR (has_ai_task = false)) AND (ai_task_sidebar_app_id IS NULL)) OR ((has_ai_task = true) AND (ai_task_sidebar_app_id IS NOT NULL))));
@@ -0,0 +1,4 @@
-- We no longer need to enforce this constraint as tasks have their own data
-- model.
ALTER TABLE workspace_builds
DROP CONSTRAINT workspace_builds_ai_task_sidebar_app_id_required;
@@ -0,0 +1,45 @@
ALTER TABLE workspace_builds ADD COLUMN ai_task_sidebar_app_id UUID;
ALTER TABLE workspace_builds ADD CONSTRAINT workspace_builds_ai_task_sidebar_app_id_fkey FOREIGN KEY (ai_task_sidebar_app_id) REFERENCES workspace_apps(id);
DROP VIEW workspace_build_with_user;
-- Restore view.
CREATE VIEW workspace_build_with_user AS
SELECT
workspace_builds.id,
workspace_builds.created_at,
workspace_builds.updated_at,
workspace_builds.workspace_id,
workspace_builds.template_version_id,
workspace_builds.build_number,
workspace_builds.transition,
workspace_builds.initiator_id,
workspace_builds.provisioner_state,
workspace_builds.job_id,
workspace_builds.deadline,
workspace_builds.reason,
workspace_builds.daily_cost,
workspace_builds.max_deadline,
workspace_builds.template_version_preset_id,
workspace_builds.has_ai_task,
workspace_builds.ai_task_sidebar_app_id,
workspace_builds.has_external_agent,
COALESCE(
visible_users.avatar_url,
'' :: text
) AS initiator_by_avatar_url,
COALESCE(
visible_users.username,
'' :: text
) AS initiator_by_username,
COALESCE(visible_users.name, '' :: text) AS initiator_by_name
FROM
(
workspace_builds
LEFT JOIN visible_users ON (
(
workspace_builds.initiator_id = visible_users.id
)
)
);
COMMENT ON VIEW workspace_build_with_user IS 'Joins in the username + avatar url of the initiated by user.';
@@ -0,0 +1,43 @@
-- We're dropping the ai_task_sidebar_app_id column.
DROP VIEW workspace_build_with_user;
CREATE VIEW workspace_build_with_user AS
SELECT
workspace_builds.id,
workspace_builds.created_at,
workspace_builds.updated_at,
workspace_builds.workspace_id,
workspace_builds.template_version_id,
workspace_builds.build_number,
workspace_builds.transition,
workspace_builds.initiator_id,
workspace_builds.provisioner_state,
workspace_builds.job_id,
workspace_builds.deadline,
workspace_builds.reason,
workspace_builds.daily_cost,
workspace_builds.max_deadline,
workspace_builds.template_version_preset_id,
workspace_builds.has_ai_task,
workspace_builds.has_external_agent,
COALESCE(
visible_users.avatar_url,
'' :: text
) AS initiator_by_avatar_url,
COALESCE(
visible_users.username,
'' :: text
) AS initiator_by_username,
COALESCE(visible_users.name, '' :: text) AS initiator_by_name
FROM
(
workspace_builds
LEFT JOIN visible_users ON (
(
workspace_builds.initiator_id = visible_users.id
)
)
);
COMMENT ON VIEW workspace_build_with_user IS 'Joins in the username + avatar url of the initiated by user.';
ALTER TABLE workspace_builds DROP COLUMN ai_task_sidebar_app_id;
@@ -0,0 +1 @@
ALTER TABLE aibridge_interceptions DROP COLUMN api_key_id;
@@ -0,0 +1,2 @@
-- column is nullable to not break interceptions recorded before this column was added
ALTER TABLE aibridge_interceptions ADD COLUMN api_key_id text;
@@ -0,0 +1,26 @@
DROP VIEW template_with_names;
-- Drop the column
ALTER TABLE templates DROP COLUMN use_terraform_workspace_cache;
-- Update the template_with_names view by recreating it.
CREATE VIEW template_with_names AS
SELECT
templates.*,
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS created_by_username,
COALESCE(visible_users.name, ''::text) AS created_by_name,
COALESCE(organizations.name, ''::text) AS organization_name,
COALESCE(organizations.display_name, ''::text) AS organization_display_name,
COALESCE(organizations.icon, ''::text) AS organization_icon
FROM
templates
LEFT JOIN
visible_users
ON
templates.created_by = visible_users.id
LEFT JOIN
organizations
ON templates.organization_id = organizations.id
;
COMMENT ON VIEW template_with_names IS 'Joins in the display name information such as username, avatar, and organization name.';
@@ -0,0 +1,33 @@
-- Default to `false`. Users will have to manually opt into the terraform workspace cache feature.
ALTER TABLE templates ADD COLUMN use_terraform_workspace_cache BOOL NOT NULL DEFAULT false;
COMMENT ON COLUMN templates.use_terraform_workspace_cache IS
'Determines whether to keep terraform directories cached between runs for workspaces created from this template. '
'When enabled, this can significantly speed up the `terraform init` step at the cost of increased disk usage. '
'This is an opt-in experience, as it prevents modules from being updated, and therefore is a behavioral difference '
'from the default.';
;
-- Update the template_with_names view by recreating it.
DROP VIEW template_with_names;
CREATE VIEW template_with_names AS
SELECT
templates.*,
COALESCE(visible_users.avatar_url, ''::text) AS created_by_avatar_url,
COALESCE(visible_users.username, ''::text) AS created_by_username,
COALESCE(visible_users.name, ''::text) AS created_by_name,
COALESCE(organizations.name, ''::text) AS organization_name,
COALESCE(organizations.display_name, ''::text) AS organization_display_name,
COALESCE(organizations.icon, ''::text) AS organization_icon
FROM
templates
LEFT JOIN
visible_users
ON
templates.created_by = visible_users.id
LEFT JOIN
organizations
ON templates.organization_id = organizations.id
;
COMMENT ON VIEW template_with_names IS 'Joins in the display name information such as username, avatar, and organization name.';
@@ -0,0 +1,82 @@
-- Restore previous view.
DROP VIEW IF EXISTS tasks_with_status;
CREATE VIEW
tasks_with_status
AS
SELECT
tasks.*,
CASE
WHEN tasks.workspace_id IS NULL OR latest_build.job_status IS NULL THEN 'pending'::task_status
WHEN latest_build.job_status = 'failed' THEN 'error'::task_status
WHEN latest_build.transition IN ('stop', 'delete')
AND latest_build.job_status = 'succeeded' THEN 'paused'::task_status
WHEN latest_build.transition = 'start'
AND latest_build.job_status = 'pending' THEN 'initializing'::task_status
WHEN latest_build.transition = 'start' AND latest_build.job_status IN ('running', 'succeeded') THEN
CASE
WHEN agent_status.none THEN 'initializing'::task_status
WHEN agent_status.connecting THEN 'initializing'::task_status
WHEN agent_status.connected THEN
CASE
WHEN app_status.any_unhealthy THEN 'error'::task_status
WHEN app_status.any_initializing THEN 'initializing'::task_status
WHEN app_status.all_healthy_or_disabled THEN 'active'::task_status
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
END
ELSE 'unknown'::task_status
END AS status,
task_app.*,
task_owner.*
FROM
tasks
CROSS JOIN LATERAL (
SELECT
vu.username AS owner_username,
vu.name AS owner_name,
vu.avatar_url AS owner_avatar_url
FROM visible_users vu
WHERE vu.id = tasks.owner_id
) task_owner
LEFT JOIN LATERAL (
SELECT workspace_build_number, workspace_agent_id, workspace_app_id
FROM task_workspace_apps task_app
WHERE task_id = tasks.id
ORDER BY workspace_build_number DESC
LIMIT 1
) task_app ON TRUE
LEFT JOIN LATERAL (
SELECT
workspace_build.transition,
provisioner_job.job_status,
workspace_build.job_id
FROM workspace_builds workspace_build
JOIN provisioner_jobs provisioner_job ON provisioner_job.id = workspace_build.job_id
WHERE workspace_build.workspace_id = tasks.workspace_id
AND workspace_build.build_number = task_app.workspace_build_number
) latest_build ON TRUE
CROSS JOIN LATERAL (
SELECT
COUNT(*) = 0 AS none,
bool_or(workspace_agent.lifecycle_state IN ('created', 'starting')) AS connecting,
bool_and(workspace_agent.lifecycle_state = 'ready') AS connected
FROM workspace_agents workspace_agent
WHERE workspace_agent.id = task_app.workspace_agent_id
) agent_status
CROSS JOIN LATERAL (
SELECT
bool_or(workspace_app.health = 'unhealthy') AS any_unhealthy,
bool_or(workspace_app.health = 'initializing') AS any_initializing,
bool_and(workspace_app.health IN ('healthy', 'disabled')) AS all_healthy_or_disabled
FROM workspace_apps workspace_app
WHERE workspace_app.id = task_app.workspace_app_id
) app_status
WHERE
tasks.deleted_at IS NULL;
@@ -0,0 +1,142 @@
-- Update task status in view.
DROP VIEW IF EXISTS tasks_with_status;
CREATE VIEW
tasks_with_status
AS
SELECT
tasks.*,
-- Combine component statuses with precedence: build -> agent -> app.
CASE
WHEN tasks.workspace_id IS NULL THEN 'pending'::task_status
WHEN build_status.status != 'active' THEN build_status.status::task_status
WHEN agent_status.status != 'active' THEN agent_status.status::task_status
ELSE app_status.status::task_status
END AS status,
-- Attach debug information for troubleshooting status.
jsonb_build_object(
'build', jsonb_build_object(
'transition', latest_build_raw.transition,
'job_status', latest_build_raw.job_status,
'computed', build_status.status
),
'agent', jsonb_build_object(
'lifecycle_state', agent_raw.lifecycle_state,
'computed', agent_status.status
),
'app', jsonb_build_object(
'health', app_raw.health,
'computed', app_status.status
)
) AS status_debug,
task_app.*,
agent_raw.lifecycle_state AS workspace_agent_lifecycle_state,
app_raw.health AS workspace_app_health,
task_owner.*
FROM
tasks
CROSS JOIN LATERAL (
SELECT
vu.username AS owner_username,
vu.name AS owner_name,
vu.avatar_url AS owner_avatar_url
FROM
visible_users vu
WHERE
vu.id = tasks.owner_id
) task_owner
LEFT JOIN LATERAL (
SELECT
task_app.workspace_build_number,
task_app.workspace_agent_id,
task_app.workspace_app_id
FROM
task_workspace_apps task_app
WHERE
task_id = tasks.id
ORDER BY
task_app.workspace_build_number DESC
LIMIT 1
) task_app ON TRUE
-- Join the raw data for computing task status.
LEFT JOIN LATERAL (
SELECT
workspace_build.transition,
provisioner_job.job_status,
workspace_build.job_id
FROM
workspace_builds workspace_build
JOIN
provisioner_jobs provisioner_job
ON provisioner_job.id = workspace_build.job_id
WHERE
workspace_build.workspace_id = tasks.workspace_id
AND workspace_build.build_number = task_app.workspace_build_number
) latest_build_raw ON TRUE
LEFT JOIN LATERAL (
SELECT
workspace_agent.lifecycle_state
FROM
workspace_agents workspace_agent
WHERE
workspace_agent.id = task_app.workspace_agent_id
) agent_raw ON TRUE
LEFT JOIN LATERAL (
SELECT
workspace_app.health
FROM
workspace_apps workspace_app
WHERE
workspace_app.id = task_app.workspace_app_id
) app_raw ON TRUE
-- Compute the status for each component.
CROSS JOIN LATERAL (
SELECT
CASE
WHEN latest_build_raw.job_status IS NULL THEN 'pending'::task_status
WHEN latest_build_raw.job_status IN ('failed', 'canceling', 'canceled') THEN 'error'::task_status
WHEN
latest_build_raw.transition IN ('stop', 'delete')
AND latest_build_raw.job_status = 'succeeded' THEN 'paused'::task_status
WHEN
latest_build_raw.transition = 'start'
AND latest_build_raw.job_status = 'pending' THEN 'initializing'::task_status
-- Build is running or done, defer to agent/app status.
WHEN
latest_build_raw.transition = 'start'
AND latest_build_raw.job_status IN ('running', 'succeeded') THEN 'active'::task_status
ELSE 'unknown'::task_status
END AS status
) build_status
CROSS JOIN LATERAL (
SELECT
CASE
-- No agent or connecting.
WHEN
agent_raw.lifecycle_state IS NULL
OR agent_raw.lifecycle_state IN ('created', 'starting') THEN 'initializing'::task_status
-- Agent is running, defer to app status.
-- NOTE(mafredri): The start_error/start_timeout states means connected, but some startup script failed.
-- This may or may not affect the task status but this has to be caught by app health check.
WHEN agent_raw.lifecycle_state IN ('ready', 'start_timeout', 'start_error') THEN 'active'::task_status
-- If the agent is shutting down or turned off, this is an unknown state because we would expect a stop
-- build to be running.
-- This is essentially equal to: `IN ('shutting_down', 'shutdown_timeout', 'shutdown_error', 'off')`,
-- but we cannot use them because the values were added in a migration.
WHEN agent_raw.lifecycle_state NOT IN ('created', 'starting', 'ready', 'start_timeout', 'start_error') THEN 'unknown'::task_status
ELSE 'unknown'::task_status
END AS status
) agent_status
CROSS JOIN LATERAL (
SELECT
CASE
WHEN app_raw.health = 'initializing' THEN 'initializing'::task_status
WHEN app_raw.health = 'unhealthy' THEN 'error'::task_status
WHEN app_raw.health IN ('healthy', 'disabled') THEN 'active'::task_status
ELSE 'unknown'::task_status
END AS status
) app_status
WHERE
tasks.deleted_at IS NULL;
@@ -0,0 +1 @@
ALTER TABLE template_version_presets DROP COLUMN last_invalidated_at;
@@ -0,0 +1 @@
ALTER TABLE template_version_presets ADD COLUMN last_invalidated_at TIMESTAMPTZ;
+3 -1
View File
@@ -127,6 +127,7 @@ func (q *sqlQuerier) GetAuthorizedTemplates(ctx context.Context, arg GetTemplate
&i.MaxPortSharingLevel,
&i.UseClassicParameterFlow,
&i.CorsBehavior,
&i.UseTerraformWorkspaceCache,
&i.CreatedByAvatarURL,
&i.CreatedByUsername,
&i.CreatedByName,
@@ -321,6 +322,7 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
&i.TemplateDisplayName,
&i.TemplateIcon,
&i.TemplateDescription,
&i.TaskID,
&i.TemplateVersionID,
&i.TemplateVersionName,
&i.LatestBuildCompletedAt,
@@ -328,7 +330,6 @@ func (q *sqlQuerier) GetAuthorizedWorkspaces(ctx context.Context, arg GetWorkspa
&i.LatestBuildError,
&i.LatestBuildTransition,
&i.LatestBuildStatus,
&i.LatestBuildHasAITask,
&i.LatestBuildHasExternalAgent,
&i.Count,
); err != nil {
@@ -805,6 +806,7 @@ func (q *sqlQuerier) ListAuthorizedAIBridgeInterceptions(ctx context.Context, ar
&i.AIBridgeInterception.StartedAt,
&i.AIBridgeInterception.Metadata,
&i.AIBridgeInterception.EndedAt,
&i.AIBridgeInterception.APIKeyID,
&i.VisibleUser.ID,
&i.VisibleUser.Username,
&i.VisibleUser.Name,
+28 -21
View File
@@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// sqlc v1.30.0
package database
@@ -3614,6 +3614,7 @@ type AIBridgeInterception struct {
StartedAt time.Time `db:"started_at" json:"started_at"`
Metadata pqtype.NullRawMessage `db:"metadata" json:"metadata"`
EndedAt sql.NullTime `db:"ended_at" json:"ended_at"`
APIKeyID sql.NullString `db:"api_key_id" json:"api_key_id"`
}
// Audit log of tokens used by intercepted requests in AI Bridge
@@ -4207,23 +4208,26 @@ type TailnetTunnel struct {
}
type Task struct {
ID uuid.UUID `db:"id" json:"id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
Name string `db:"name" json:"name"`
WorkspaceID uuid.NullUUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateParameters json.RawMessage `db:"template_parameters" json:"template_parameters"`
Prompt string `db:"prompt" json:"prompt"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
DeletedAt sql.NullTime `db:"deleted_at" json:"deleted_at"`
Status TaskStatus `db:"status" json:"status"`
WorkspaceBuildNumber sql.NullInt32 `db:"workspace_build_number" json:"workspace_build_number"`
WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"`
WorkspaceAppID uuid.NullUUID `db:"workspace_app_id" json:"workspace_app_id"`
OwnerUsername string `db:"owner_username" json:"owner_username"`
OwnerName string `db:"owner_name" json:"owner_name"`
OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
ID uuid.UUID `db:"id" json:"id"`
OrganizationID uuid.UUID `db:"organization_id" json:"organization_id"`
OwnerID uuid.UUID `db:"owner_id" json:"owner_id"`
Name string `db:"name" json:"name"`
WorkspaceID uuid.NullUUID `db:"workspace_id" json:"workspace_id"`
TemplateVersionID uuid.UUID `db:"template_version_id" json:"template_version_id"`
TemplateParameters json.RawMessage `db:"template_parameters" json:"template_parameters"`
Prompt string `db:"prompt" json:"prompt"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
DeletedAt sql.NullTime `db:"deleted_at" json:"deleted_at"`
Status TaskStatus `db:"status" json:"status"`
StatusDebug json.RawMessage `db:"status_debug" json:"status_debug"`
WorkspaceBuildNumber sql.NullInt32 `db:"workspace_build_number" json:"workspace_build_number"`
WorkspaceAgentID uuid.NullUUID `db:"workspace_agent_id" json:"workspace_agent_id"`
WorkspaceAppID uuid.NullUUID `db:"workspace_app_id" json:"workspace_app_id"`
WorkspaceAgentLifecycleState NullWorkspaceAgentLifecycleState `db:"workspace_agent_lifecycle_state" json:"workspace_agent_lifecycle_state"`
WorkspaceAppHealth NullWorkspaceAppHealth `db:"workspace_app_health" json:"workspace_app_health"`
OwnerUsername string `db:"owner_username" json:"owner_username"`
OwnerName string `db:"owner_name" json:"owner_name"`
OwnerAvatarUrl string `db:"owner_avatar_url" json:"owner_avatar_url"`
}
type TaskTable struct {
@@ -4293,6 +4297,7 @@ type Template struct {
MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"`
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
UseTerraformWorkspaceCache bool `db:"use_terraform_workspace_cache" json:"use_terraform_workspace_cache"`
CreatedByAvatarURL string `db:"created_by_avatar_url" json:"created_by_avatar_url"`
CreatedByUsername string `db:"created_by_username" json:"created_by_username"`
CreatedByName string `db:"created_by_name" json:"created_by_name"`
@@ -4342,6 +4347,8 @@ type TemplateTable struct {
// Determines whether to default to the dynamic parameter creation flow for this template or continue using the legacy classic parameter creation flow.This is a template wide setting, the template admin can revert to the classic flow if there are any issues. An escape hatch is required, as workspace creation is a core workflow and cannot break. This column will be removed when the dynamic parameter creation flow is stable.
UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"`
CorsBehavior CorsBehavior `db:"cors_behavior" json:"cors_behavior"`
// Determines whether to keep terraform directories cached between runs for workspaces created from this template. When enabled, this can significantly speed up the `terraform init` step at the cost of increased disk usage. This is an opt-in experience, as it prevents modules from being updated, and therefore is a behavioral difference from the default.
UseTerraformWorkspaceCache bool `db:"use_terraform_workspace_cache" json:"use_terraform_workspace_cache"`
}
// Records aggregated usage statistics for templates/users. All usage is rounded up to the nearest minute.
@@ -4445,7 +4452,8 @@ type TemplateVersionPreset struct {
// Short text describing the preset (max 128 characters).
Description string `db:"description" json:"description"`
// URL or path to an icon representing the preset (max 256 characters).
Icon string `db:"icon" json:"icon"`
Icon string `db:"icon" json:"icon"`
LastInvalidatedAt sql.NullTime `db:"last_invalidated_at" json:"last_invalidated_at"`
}
type TemplateVersionPresetParameter struct {
@@ -4663,6 +4671,7 @@ type Workspace struct {
TemplateDisplayName string `db:"template_display_name" json:"template_display_name"`
TemplateIcon string `db:"template_icon" json:"template_icon"`
TemplateDescription string `db:"template_description" json:"template_description"`
TaskID uuid.NullUUID `db:"task_id" json:"task_id"`
}
type WorkspaceAgent struct {
@@ -4938,7 +4947,6 @@ type WorkspaceBuild struct {
MaxDeadline time.Time `db:"max_deadline" json:"max_deadline"`
TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
AITaskSidebarAppID uuid.NullUUID `db:"ai_task_sidebar_app_id" json:"ai_task_sidebar_app_id"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
InitiatorByAvatarUrl string `db:"initiator_by_avatar_url" json:"initiator_by_avatar_url"`
InitiatorByUsername string `db:"initiator_by_username" json:"initiator_by_username"`
@@ -4970,7 +4978,6 @@ type WorkspaceBuildTable struct {
MaxDeadline time.Time `db:"max_deadline" json:"max_deadline"`
TemplateVersionPresetID uuid.NullUUID `db:"template_version_preset_id" json:"template_version_preset_id"`
HasAITask sql.NullBool `db:"has_ai_task" json:"has_ai_task"`
AITaskSidebarAppID uuid.NullUUID `db:"ai_task_sidebar_app_id" json:"ai_task_sidebar_app_id"`
HasExternalAgent sql.NullBool `db:"has_external_agent" json:"has_external_agent"`
}
+7 -2
View File
@@ -1,6 +1,6 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// sqlc v1.30.0
package database
@@ -269,6 +269,9 @@ type sqlcQuerier interface {
GetOrganizationResourceCountByID(ctx context.Context, organizationID uuid.UUID) (GetOrganizationResourceCountByIDRow, error)
GetOrganizations(ctx context.Context, arg GetOrganizationsParams) ([]Organization, error)
GetOrganizationsByUserID(ctx context.Context, arg GetOrganizationsByUserIDParams) ([]Organization, error)
// GetOrganizationsWithPrebuildStatus returns organizations with prebuilds configured and their
// membership status for the prebuilds system user (org membership, group existence, group membership).
GetOrganizationsWithPrebuildStatus(ctx context.Context, arg GetOrganizationsWithPrebuildStatusParams) ([]GetOrganizationsWithPrebuildStatusRow, error)
GetParameterSchemasByJobID(ctx context.Context, jobID uuid.UUID) ([]ParameterSchema, error)
GetPrebuildMetrics(ctx context.Context) ([]GetPrebuildMetricsRow, error)
GetPrebuildsSettings(ctx context.Context) (string, error)
@@ -340,6 +343,7 @@ type sqlcQuerier interface {
GetTailnetTunnelPeerBindings(ctx context.Context, srcID uuid.UUID) ([]GetTailnetTunnelPeerBindingsRow, error)
GetTailnetTunnelPeerIDs(ctx context.Context, srcID uuid.UUID) ([]GetTailnetTunnelPeerIDsRow, error)
GetTaskByID(ctx context.Context, id uuid.UUID) (Task, error)
GetTaskByOwnerIDAndName(ctx context.Context, arg GetTaskByOwnerIDAndNameParams) (Task, error)
GetTaskByWorkspaceID(ctx context.Context, workspaceID uuid.UUID) (Task, error)
GetTelemetryItem(ctx context.Context, key string) (TelemetryItem, error)
GetTelemetryItems(ctx context.Context) ([]TelemetryItem, error)
@@ -667,8 +671,9 @@ type sqlcQuerier interface {
// Cancels all pending provisioner jobs for prebuilt workspaces on a specific preset from an
// inactive template version.
// This is an optimization to clean up stale pending jobs.
UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg UpdatePrebuildProvisionerJobWithCancelParams) ([]uuid.UUID, error)
UpdatePrebuildProvisionerJobWithCancel(ctx context.Context, arg UpdatePrebuildProvisionerJobWithCancelParams) ([]UpdatePrebuildProvisionerJobWithCancelRow, error)
UpdatePresetPrebuildStatus(ctx context.Context, arg UpdatePresetPrebuildStatusParams) error
UpdatePresetsLastInvalidatedAt(ctx context.Context, arg UpdatePresetsLastInvalidatedAtParams) ([]UpdatePresetsLastInvalidatedAtRow, error)
UpdateProvisionerDaemonLastSeenAt(ctx context.Context, arg UpdateProvisionerDaemonLastSeenAtParams) error
UpdateProvisionerJobByID(ctx context.Context, arg UpdateProvisionerJobByIDParams) error
UpdateProvisionerJobLogsLength(ctx context.Context, arg UpdateProvisionerJobLogsLengthParams) error
+49 -6
View File
@@ -6664,6 +6664,23 @@ func TestTasksWithStatusView(t *testing.T) {
StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
}
case database.ProvisionerJobStatusCanceling:
jobParams = database.ProvisionerJob{
OrganizationID: org.ID,
Type: database.ProvisionerJobTypeWorkspaceBuild,
InitiatorID: user.ID,
StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CanceledAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
}
case database.ProvisionerJobStatusCanceled:
jobParams = database.ProvisionerJob{
OrganizationID: org.ID,
Type: database.ProvisionerJobTypeWorkspaceBuild,
InitiatorID: user.ID,
StartedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CompletedAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
CanceledAt: sql.NullTime{Valid: true, Time: dbtime.Now()},
}
default:
t.Errorf("invalid build status: %v", buildStatus)
}
@@ -6816,6 +6833,28 @@ func TestTasksWithStatusView(t *testing.T) {
expectWorkspaceAgentValid: false,
expectWorkspaceAppValid: false,
},
{
name: "CancelingBuild",
buildStatus: database.ProvisionerJobStatusCanceling,
buildTransition: database.WorkspaceTransitionStart,
expectedStatus: database.TaskStatusError,
description: "Latest workspace build is canceling",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: false,
expectWorkspaceAppValid: false,
},
{
name: "CanceledBuild",
buildStatus: database.ProvisionerJobStatusCanceled,
buildTransition: database.WorkspaceTransitionStart,
expectedStatus: database.TaskStatusError,
description: "Latest workspace build was canceled",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: false,
expectWorkspaceAppValid: false,
},
{
name: "StoppedWorkspace",
buildStatus: database.ProvisionerJobStatusSucceeded,
@@ -6943,24 +6982,26 @@ func TestTasksWithStatusView(t *testing.T) {
buildStatus: database.ProvisionerJobStatusSucceeded,
buildTransition: database.WorkspaceTransitionStart,
agentState: database.WorkspaceAgentLifecycleStateStartTimeout,
expectedStatus: database.TaskStatusUnknown,
description: "Agent start timed out",
appHealths: []database.WorkspaceAppHealth{database.WorkspaceAppHealthHealthy},
expectedStatus: database.TaskStatusActive,
description: "Agent start timed out but app is healthy, defer to app",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: true,
expectWorkspaceAppValid: false,
expectWorkspaceAppValid: true,
},
{
name: "AgentStartError",
buildStatus: database.ProvisionerJobStatusSucceeded,
buildTransition: database.WorkspaceTransitionStart,
agentState: database.WorkspaceAgentLifecycleStateStartError,
expectedStatus: database.TaskStatusUnknown,
description: "Agent failed to start",
appHealths: []database.WorkspaceAppHealth{database.WorkspaceAppHealthHealthy},
expectedStatus: database.TaskStatusActive,
description: "Agent start failed but app is healthy, defer to app",
expectBuildNumberValid: true,
expectBuildNumber: 1,
expectWorkspaceAgentValid: true,
expectWorkspaceAppValid: false,
expectWorkspaceAppValid: true,
},
{
name: "AgentShuttingDown",
@@ -7081,6 +7122,8 @@ func TestTasksWithStatusView(t *testing.T) {
got, err := db.GetTaskByID(ctx, task.ID)
require.NoError(t, err)
t.Logf("Task status debug: %s", got.StatusDebug)
require.Equal(t, tt.expectedStatus, got.Status)
require.Equal(t, tt.expectBuildNumberValid, got.WorkspaceBuildNumber.Valid)
File diff suppressed because it is too large Load Diff

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