This repository was archived by the owner on Dec 27, 2025. It is now read-only.
sync#2
Open
cheesycod wants to merge 599 commits into
Open
Conversation
…raries and cli commands. (#813) This is a refactor PR that splits out the Batteries specific behavior from the CliVFS
Updates implementation of `fs.watch` with the `deque` from batteries instead of `table.remove(_, 1)`. This still doesn't help with resolvig the perf issues we've been having with `fs.watch` but using the deque is still better than removing from the front of a table
Matches the following Selene rule: https://kampfkarren.github.io/selene/lints/duplicate_keys.html#duplicate_keys
This PR implements two next steps for lute lint's configuration system:
rule context and rule-specific ignores.
`Context` is a table of `globals` and rule specific `options`, as
configured by the user. For example, given a configuration of:
```
{
...,
globals = {
myGlobal = 1
},
rules = {
myRule = {
options = {
myOption = 1
}
}
}
}
```
we will the following context to each call of `myRule`:
```
{
globals = {
myGlobal = 1
},
options = {
myOption = 1
}
}
```
This enables rule authors to write logic w/ configurability in mind, and
extend their analyses to use-cases beyond the default.
Rule-specific ignores extend the global-lint ignores (implemented in
this PR), but are evaluated per-rule. This enables more granular ignore
behavior, where we can effectively turn off rules for certain files /
paths.
Also updates lute lint's behavior to always run default rules unless the option is specified
**Lute**: Updated from `0.1.0-nightly.20260205` to `0.1.0-nightly.20260213` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/0.1.0-nightly.20260213 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* --------- Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: skberkeley <kanosuesora@gmail.com>
Once the necessary change makes it into Mandolin, this allows us to grey out unused variables
Found a bug when serializing nested MetatableTypes when testing the
`typeofmodule` API on the modules in `definitions/` and it passed the
current test cases because I was only testing shallow metatables, but
when we have nested metatables like that in `@lute/time` and we have
things like
```lua
export type Duration = setmetatable<Frozen, {
read __metatable: "The metatable is locked!",
read __index: typeof(table.freeze(duration_ops)),
read __add: (Duration, Duration) -> Duration,
read __sub: (Duration, Duration) -> Duration,
read __eq: (Duration, Duration) -> boolean,
read __lt: (Duration, Duration) -> boolean,
read __le: (Duration, Duration) -> boolean,
}>
```
The indices were getting messed up because I was creating an extra table
for the metatable, which isn't correct bc we're treating a metatable as
just a table with an extra `metatable` field). We don't need to do that
because when `traverse(mtv.table)` enters the `serialize(TableType)`
case, that already handles creating that table.
This fixes any issues I have with calling the Type Serializer on all of
the `.luau` files in `definitions/`
This PR adds support for the `off` field on a rule's configuration, allowing users to disable rules via lute lint config.
This PR adds support for customizing a rule's severity via lute lint configuration. The change is pretty small, and just sets each detected `violation`'s severity according to the configured severity, if it exists, before we add the `violation` to the cumulative `violations` table.
`lute lint` will fail if any of the paths derived from the passed `-r`
arg are _not_ valid lint rules. I think it'd be a nicer UX for consumers
to be able to call `lute lint -r {path_to_suite}/src ...` rather than
maintaining some dir that is exclusively the rule implementations
themselves (which will prob b a bunch of re-exports in most cases
anyway).
This PR refactors the loading process to silently ignore invalid lint
rules, such that `lute lint` will exhaustively load all rules underneath
the path passed to `-r`, without requiring each discovered .luau file to
be a rule implementation
felt the need for this refactor given the addition of configs to lute lint
…l flags (#829) I went through `tools/check-faillist.txt` and tried to fix as many errors as I could reasonably find. There are definitely some errors that I've fixed by paving over bugs in the new solver (for example all of the `table.sort` invocations). Additionally I've noted some interesting new solver bugs: * Comparing anything with `nil` should not be an error * Errant warning on `#` on a metatable with `__len` * There are some spots where we need better table types: read-only indexers, for example. * There's a couple refinement bugs in `traverseTable` in `lute/batteries/pp.luau`, one of which seems very new. * We should add an overload to pcall that allows taking a function that returns an empty pack. I've also updated the VSCode workspace to enable all flags in `luau-lsp`: this should help with some reported mismatches between the faillist and folks editor experience.
This ensures that they don't leak into the type definitions generated by `lute setup`. This was previously causing issues because they relied on types related to `.gitignore` parsing, which they were requiring using a relative path which was breaking in the typedef files.
Refactors some Luau AST types to be more consistent. The general naming convention is `Ast<node category><node type>`, ie `AstExprBinary`. _Only_ node types which are part of the category in their name should follow this convention, to avoid confusion around whether they are full nodes or not. For example, we previously had `AstTypeFunctionParameter` which I renamed to `AstFunctionTypeParameter` and `AstExprTableItemList` which I renamed to `AstTableExprListItem`. I also simplified some of the top level AST type definitions, since our tagged union inference is stronger now.
When running `lute lint ./ -c ./config.lint.luau` locally, Vighnesh ran into an issue with the configs ignore logic: ``` @std/path/posix/init.luau:209: Cannot compute relative path between absolute and relative paths stacktrace: [C] function error @std/path/posix/init.luau:209 function relative @std/path/init.luau:83 function relative @cli/lib/parseIgnores.luau:165 function isIgnored @cli/lint/init.luau:448 function lintPaths @cli/lint/init.luau:588 function main @cli/lint/init.luau:611 ``` Since Vighnesh passed a relative path for the `-c` arg, the `configPath` and `rootLocation` derived from it in the main linting flow were both using relative paths, thus our error. As the linter walks the fs, it checks each against our `ignoreData` to determine if the current path should be ignored / linted. All of these walked paths are absolute, which is ensured by [this logic](https://github.com/luau-lang/lute/blob/primary/lute/cli/commands/lib/files.luau#L55-L57) in `getSourceFiles` (where we derive lintee filepaths from). Thus, if `rootLocation` is relative, an error will be thrown. To avoid this, we can normalize the `rootLocation` to be absolute **always**
This is in preparation for the serializer actually freezing AST node tables
This PR adds a snapshot testing framework to `lute test`, that runs `*.snap.luau` files, captures their output, and compares it to a corresponding `.snap` file on disk. Under the hood, this just takes the `lute` exec path, and executes `lute run` on the `*.snap.luau` file. What this PR does: - Normalizing path separators to POSIX as well as replaces ocurrences of cwd() with <ROOT>. This means that tests can run on any machine, any platform, and will hopefully produce the same output. - Color output - Diffs indicating the delta between the snapshot and the actual invocation. - Support for interactively resolving differences - Examples - I've rewritten the standard library tests for `@std/test` to use this framework. Not in this PR(but 100% coming in upcoming ones): - Support for customizing the arguments passed to `lute` - @hgoldstein has suggested a design where each directory of snapshot files has an ARGS configuration(or equivalent) that specifies arguments on a per directory basis. I am thinking about using a .luau file to do the configuration for this instead. - I would need the above feature in order to start effectively testing this framework, since that would let me generate snapshots of the output of this command itself. - Adding this to CI - Rewriting tests that serialize things to /tmp/ to use this
Did another pass of the faillist. I've added some more detailed comments around the spots where `table.insert` is falling over, but most of these are not legitimate errors / are more "nothing is going wrong but we have to hold Luau's hand."
`deque` is written in the current Luau OOP style: slap a metatable with `__index` and you're off to the races. The typing doesn't indicate this, which creates errant lint warnings of: ``` Using '#' on a table without an array part is likely a bug ``` Originally I thought this was an Analysis issue, but I realized that we aren't even _telling_ Analysis that `deque` has a metatable, so it thinks `__len` is just a normal table property. I added one or two annotations as a smoke check against horribly breaking the typing of `deque`.
There is no `.luaurc` file included in the generated type definitions folder. Files within the folder using any lute-reserved alias, like the syntax types, will yield errors when consumed. This PR ensures `lute setup` generates a `.luaurc` file in the type definitions
#834) This supports reporting patterns like the following, where `t` is unused because it's only inserted into: ```luau local t = {} table.insert(t, 2) ```
We seem to have ended up with two separate folders for runtime tests authored in luau, which seems weird and we can obviously clean that up.
Resolves #846 by implementing the three comparison metamethods for `Instants` in Lute.
This PR adds supports for loading rules from paths specified in the lute lint config file under `config.lute.lint.rules.paths`.
Tests added in this recently merged [PR](#834) (merged a couple of hours ago) were broken by this [PR](#822) that merged one hour ago but had passed CI a few days and not been updated since. These failures are [blocking release ](https://github.com/luau-lang/lute/actions/runs/22466935866) This PR fixes said tests
Not too interesting here. One of these is a case where we do some platform specific stuff, so Luau can't actually refine paths based on this information.
Matches https://kampfkarren.github.io/selene/lints/empty_if.html --------- Co-authored-by: ariel <arielweiss@roblox.com>
…gnees" (#842) AFACT: "assignee" is whatever we want it to be, and the team has signaled that they'd like to automatically be assigned to their own PRs s.t. they show up in our project kanban board. --------- Co-authored-by: ariel <arielweiss@roblox.com>
Extend cross-VM marshalling with `vector` type support. Related to #1080.
…n parts (#1105) Improves `@std/json` correctness around two serialization edge cases: - Rejects non-finite numbers (`math.huge`, `-math.huge`, `math.nan`) instead of emitting invalid JSON tokens - We could alternatively emit `null` if we don't want to be as annoying with errors and match what some serializers do, curious if there are any opinions on this - Grows the serialization buffer until the pending write fits, fixing failures for very large strings or object keys --------- Co-authored-by: Noah Winn <111249648+nwinn-student@users.noreply.github.com>
`lute run` supports discovering scripts located in the `.lute` folder of your workspace as an affordance for "extending" the lute executable. For example, scripts like our example `luthier` and `bootstrap` ones let you invoke commands like `lute bootstrap` or `lute luthier`. #1101 raised the issue of discoverability of the scripts in this folder, and proposed a `--list` flag that we could provide to list them out. This PR implements exactly that. The output is fairly straightforward, just an alphabetized list of the commands under a commands header, e.g. for the `lute` repository itself right now: ``` Commands bootstrap luthier ``` Closes #1101.
Extend cross-VM marshalling with `buffer` type support. Related to #1080.
Implements a simple `assert.never` utility, so folks can easily negate any assertion. This is generally useful, a familiar convention for Jest Luau users, and offers some assertions the existing lib fails to directly expose i.e asserting that a function does not throw. We modify each assertion function's signature to: `(negate: boolean, ...)` such that `reqassert` can easily construct negated assertions, without needing a separate implementation for each negation. I found this minimally intrusive, but open to ideas to slim down the surface even more if folks have any Added snapshot tests for new negated assertions --------- Co-authored-by: ariel <aweiss@hey.com>
This wrapper is unnecessary given the type contract we offer and intend to give resulting in unnecessary overhead.
It's generally useful for command-line programs to be able to respond to various OS signals, especially interrupt or quit signals. This comes up trivially with user inputs to command-line programs, anything that runs continuously/interactively/etc. We can expose a fairly straightforward API here to deal with this, mirroring roughly what's available in node. `process.onSignal` will take a signal by name and a callback to register for responding to that signal, and give you a handle for the signal registration. If you wish to later unregister that signal, you can do so by calling `close` on the handle. This is consistent with our existing filesystem API, for instance, which produces file handles. We also include `process.pid` to give you the current process ID, which enables us to write some tests sending signals to the process we're currently running. Implements #1096.
Optimizes `@std/json` serialization/deserialization by reducing repeated string and parsing work in hot paths: - Adds a per-serialize-call cache for escaped object keys - Caches hot serializer buffer/cursor locals in string write paths - Rewrites number parsing to a byte-scanning path with a fast integer case - Removes redundant whitespace scans in object parsing - Caps cached keys at 64 bytes to avoid retaining oversized key strings - Changes checkState so it lowers (thanks @nwinn-student!) | Dataset | Operation | Before | After | Speedup | |---|---|---:|---:|---:| | `tools/dataset.json` | Deserialize | 33.42 MB/s | 36.86 MB/s | 1.10x | | `tools/dataset.json` | Serialize | 31.39 MB/s | 59.71 MB/s | 1.90x | | `tools/dataset-large.json` | Deserialize | 27.15 MB/s | 31.34 MB/s | 1.15x | | `tools/dataset-large.json` | Serialize | 31.80 MB/s | 59.09 MB/s | 1.86x | Deserialization improved by roughly 10-15%, serialization by roughly 86-90%. I didn't commit the json bench but may add it on, just didn't want to make the diff look huge with JSON lol.
- Server closing is now idempotent - Preserve embedded `\0` bytes in plain string server responses (table responses already did) - Make server WebSocket upgrades safer by retaining and invalidating upgrade context instead of exposing raw request/response pointers as light userdata --------- Co-authored-by: Cursor <cursoragent@cursor.com>
) Because of the recursive implementation of `table` handling in cross-VM marshaling, deep or cyclical nesting will eventually lead to `stack overflow` and crash the entire runtime with a `segfault`. I could move the `table` processing to the `heap` with additional optimizations, such as pointers to unique values in nested tables, but this requires a deeper refactoring. Let me know if that's needed. In the meantime, let's at least add tests and ensure we fail with a readable error (`Failed to copy arguments between VMs`) and the location where it was triggered, instead of a `segfault`. Resolves #1117.
…allback reference. (#1122) I want to re-use the Signal Handling code written here to augment a `TTYHandle` with the ability to respond to SIGWINCH events. I might want to run regular C++ code in response to a signal, or even supply a different Luau Callback Ref at a later time, unrelated to the current context the Signal Handle was constructed in. This PR exposes the signal handle in a header file, makes it dispatch a regular C++ lambda, and tweaks the constructor so it's not tied to a lua_State* directly.
I wanted to improve a lot of the obvious tech debt-y kinds of things in the TOML library code. Most of this is transforming a lot of the mapping processes that were big series of branches into singular table lookups to resolve them, there's also some clean up of whitespace, conditional logic, etc. There's a negligible performance impact measured on my machine (within noise), but I think maintainability is reasonably improved with the tables.
…ew Type Solver. (#1125) This isn't strictly necessary since I think we're currently ignoring it in CI, but a few small changes to `unzip` have it passing in the New Type Solver, so I figured it was worth putting up. My editor also seems to have fixed whitespace inconsistencies in the file which is another minor nice-to-have.
CI seemingly hasn't been running typechecking because we've been using globs with `**`, which apparently doesn't work on GHA's Ubuntu because globstar is off by default. I've updated our `lute check` invocations to instead use `find`, and fixed some legitimate type errors that snuck their way in since we got rid of the type checking faillist.
As part of the work to split out AST nodes vs CST nodes in Lute's syntax library, this PR renames AST node types and references to ASTs generally to refer to CSTs, since that's what we actually operate on today.
**Luau**: Updated from `0.720` to `0.722` **Release Notes:** https://github.com/luau-lang/luau/releases/tag/0.722 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* --------- Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: skberkeley <kanosuesora@gmail.com>
Our docs builds have been broken, and we discovered #1128 recently, which both share the same underlying cause. The initial debug build of `lute0` during bootstrapping uses the same folder as the "luthier managed" build folders we have. While it does a clean luthier build after, it does so in a release configuration. So, on our CI machines (and in a local setup where you bootstrap and then start developing), you end up in a bad state for your debug builds. The situation would be resolved by doing a clean debug build, but it's easy to forget that, and in the case of our CI environment, we likely don't want to force all of the builds into being clean ones. This PR changes `bootstrap.sh` to bootstrap into a separate folder, so it will never be reused by debug builds, and prevent running into the situation where you incrementally rebuild into a bad state for your `debug` build. Fixes #1128.
Distribute walking input paths and linting files across workers. Number
of workers capped by the minimum of available system threads and # of
lintee files.
side note: it'd be _reallyyyy_ sweet if we had documentation on the `vm`
lib and how to use it, as it took me a while to figure out what it's
constraints were and how to work around them. If i'm missing something,
pls lmk 😄
## Testing
All tests passing.
Also manually sanity checked on some local repos with the script in the
collapsable below. Verified that every linted file had same the # of
violations when linted with old / new build. Seeing pretty big
improvements.
**Comparing 5/08 nightly release (default) against release build from
this branch (parallel)**
| Repo | Old | New | Diff | Diff % | Old Violations | New Violations |
Violation Diff |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| lua-apps | 46.12s | 7.75s | 38.38s | 83.2% | 22943 | 22943 | 0 |
| foundation | 2.47s | 0.56s | 1.90s | 77.2% | 855 | 855 | 0 |
| lute | 0.65s | 0.26s | 0.39s | 60.0% | 23 | 23 | 0 |
<details>
<summary>Test script</summary>
```
local process = require("@std/process")
local path = require("@std/path")
local json = require("@std/json")
local types = require("./lute/cli/commands/lint/types")
local SEVERITY_MAP: { [number]: types.severity } = {
[1] = "error",
[2] = "warning",
[3] = "info",
[4] = "hint",
}
local function convertRange(range: any): { beginLine: number, beginColumn: number, endLine: number, endColumn: number }
return {
beginLine = range.start.line + 1,
beginColumn = range.start.character + 1,
endLine = range["end"].line + 1,
endColumn = range["end"].character,
}
end
local function convertDiagnostic(item: any, sourcepath: string): types.LintViolation
local violation: types.LintViolation = {
lintname = item.code,
message = item.message,
severity = (SEVERITY_MAP[item.severity] or "warning") :: types.severity,
location = convertRange(item.range) :: any,
sourcepath = path.parse(sourcepath),
target = item.codeDescription,
}
if item.suggestedfix then
violation.suggestedfix = {
fix = item.suggestedfix.fix,
location = if item.suggestedfix.range then convertRange(item.suggestedfix.range) :: any else nil,
}
end
return violation
end
local function parseLintJsonOutput(jsonString: string): { [string]: { types.LintViolation } }
local jsonStart = string.find(jsonString, "{")
if not jsonStart then
return {}
end
local parsed = json.deserialize(jsonString:sub(jsonStart, #jsonString)) :: any
if not parsed or not parsed.items then
return {}
end
local violationsByFile: { [string]: { types.LintViolation } } = {}
for _, fileEntry in parsed.items do
local filePath = fileEntry.uri :: string
local violations: { types.LintViolation } = {}
for _, item in fileEntry.items do
table.insert(violations, convertDiagnostic(item, filePath))
end
violationsByFile[filePath] = violations
end
return violationsByFile
end
local function countViolations(results: { [string]: { types.LintViolation } }): number
local count = 0
for _, violations in results do
count += #violations
end
return count
end
local function formatSeconds(value: number): string
return string.format("%.2fs", value)
end
local function formatPercent(value: number): string
return string.format("%.1f%%", value)
end
-- local build = path.join(".", "build", "xcode", "debug", "lute", "cli", "lute")
local releaseBuild = path.join(".", "build", "xcode", "release", "lute", "cli", "lute")
local matrix: { [string]: string } = {
lute = "./",
["lua-apps"] = "../roblox/lua-apps",
["foundation"] = "../roblox/foundation",
}
type Result = {
repo: string,
old: number,
new: number,
diffSeconds: number,
diffPercent: number,
oldViolations: number,
newViolations: number,
violationDiff: number,
}
local results: { Result } = {}
for repo, repoPath in matrix do
local start = os.clock()
local normalLute = process.run({ "lute", "lint", "-j", repoPath })
local normalTime = os.clock() - start
start = os.clock()
local parallelLint = process.run({ path.format(releaseBuild), "lint", "-j", repoPath })
local parallelTime = os.clock() - start
local specialResults = parseLintJsonOutput(parallelLint.stdout)
local normalResults = parseLintJsonOutput(normalLute.stdout)
for file, violations in specialResults do
local normalViolations = normalResults[file]
assert(normalViolations ~= nil, `Missing normal lint results for {file}`)
assert(#violations == #normalViolations, `Violation count mismatch for {file}`)
end
for file, violations in normalResults do
local specialViolations = specialResults[file]
assert(specialViolations ~= nil, `Missing parallel lint results for {file}`)
assert(#violations == #specialViolations, `Violation count mismatch for {file}`)
end
local normalViolationCount = countViolations(normalResults)
local parallelViolationCount = countViolations(specialResults)
local diffSeconds = normalTime - parallelTime
local diffPercent = if normalTime > 0 then (diffSeconds / normalTime) * 100 else 0
table.insert(results, {
repo = repo,
old = normalTime,
new = parallelTime,
diffSeconds = diffSeconds,
diffPercent = diffPercent,
oldViolations = normalViolationCount,
newViolations = parallelViolationCount,
violationDiff = parallelViolationCount - normalViolationCount,
})
end
-- pretty print results in markdown table
print("| Repo | Old | New | Diff | Diff % | Old Violations | New Violations | Violation Diff |")
print("| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |")
for _, result in results do
print(
`| {result.repo} | {formatSeconds(result.old)} | {formatSeconds(result.new)} | {formatSeconds(
result.diffSeconds
)} | {formatPercent(result.diffPercent)} | {result.oldViolations} | {result.newViolations} | {result.violationDiff} |`
)
end
```
</details>
As part of the planned refactor to add AST parsing to `@std/syntax` (not just CST parsing), I would like CST nodes to subtype covariantly against AST nodes. That is, any program that deals with ASTs should be able to run even if at runtime it receives a CST instead of an AST. In parallel, I would like `Punctuated` to be more ergonomic to program with when dealing with just an AST. In particular, someone programming an the AST version of `Punctuated` will not interact with `separators`, and neither should they have to index into `nodes` every time they see `Punctuated`. This PR makes these changes to the current version of the `Punctuated`, in advance of adding an AST-specific version. Specifically, it moves `Punctuated`'s subnodes from an array stored in the `nodes` field to the array entries in `Punctuated` itself, and adds an `__iter` override to support iterating over those nodes. Finally, we also rename `Punctuated` to `CstPunctuated`.
Part of the refactor of `@std/syntax`, I plan to add `AstParseResult` in a followup
The Luau library is getting rather large to work with and is will be super unwieldy to work with if I add the AST types in the same files. This PR splits out syntax-specific items from `@lute/luau` into a new `@lute/syntax` library. I also split out the CST types into their own submodule on the `@std` side. I plan to move the parsing library into `@lute/syntax` in a followup
Followup to #1149 , completing the separation of syntax-specific things into `@lute/syntax`
**Lute**: Updated from `1.0.1-nightly.20260515` to `1.0.1-nightly.20260529` **Release Notes:** https://github.com/luau-lang/lute/releases/tag/v1.0.1-nightly.20260529 --- *This PR was automatically created by the [Update Luau workflow](https://github.com/luau-lang/lute/actions/workflows/update-prs.yml)* Co-authored-by: aatxe <744293+aatxe@users.noreply.github.com> Co-authored-by: ariel <arielweiss@roblox.com>
This PR attempts to speed up bootstrap builds for lute CI by doing the following: 1. Try to fetch dependencies in extern/ in parallel - there is no reason we need to do these serially. 2. After fetching dependencies, compute the same hash produced by luthier. This avoids us having to refetch those dependencies when building the actual `lute` binary that bootstrap produces. 3. Do a bit less work in cmake for dependencies. In addition to this, I've also setup ccache for us. We'll use `actions/cache@v4` to cache the .ccache directory. We invalidate and recompute the cache on merges to `primary`, but changes on your branch will just load the cache from primary. When testing locally, I've brought bootstrap down to about a minute from two minutes.
I hit auto-merge on my previous PR and missed some review comments to the .gitignore and README.
We recently got a report of an illegal move operation happening only in CI in #1147 when trying to use `lute pkg install`. I investigated the issue, and the underlying cause here is not that the `move` itself is failing. In GitHub Actions, `/tmp` and `/github/home` are different devices, and the underlying move (it's called "rename" in the syscalls) only works within a device. I had written fall-back code for this case that has us do a copy and then remove, but the fallback code is bugged. It doesn't happen locally since you don't have the same filesystem split, and so you don't hit the fallback. The fix is to make the fallback path deal properly with directories (and symbolic links), which we do here in this PR. We also add an explicit test case that does a move from the temporary directory into the home directory, just like `lute pkg install` does, which _should_ mean that our CI flows for this function now explicitly test the fallback case. It's harder to have a local test available for this since we can't really guarantee the presence or absence of external devices to test with, but you can follow the procedures in the CI script locally to set up such a device locally to test with.
This is causing CI to fail intermittently, so for now, let's just bump the timeout.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.