Skip to content
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
mluau:primaryfrom
luau-lang:primary
Open

sync#2
cheesycod wants to merge 599 commits into
mluau:primaryfrom
luau-lang:primary

Conversation

@cheesycod

Copy link
Copy Markdown

No description provided.

Vighnesh-V and others added 30 commits February 12, 2026 14:32
…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
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>
tyulpan and others added 30 commits May 20, 2026 11:15
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.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.