Skip to content

Support caching bevy_lint in its Github Action #530

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

BD103
Copy link
Member

@BD103 BD103 commented Jul 21, 2025

This PR adds support for caching the compiled bevy_lint and bevy_lint_driver binaries in the Github Action. This can significantly speed up the time it takes to install the linter in CI.

Usage

Check out the rendered documentation! The biggest notes are:

You can also check whether there was a cache hit, but that's mostly useful for internal testing.

Performance

The CI run for aa51a8e show the performance benefits. The "Cache miss" jobs are when the linter is built from scratch, while the "Cache hit" jobs are when the linter is downloaded from the cache. The times are summarized below:

OS Build from Scratch From Cache
Ubuntu 67s - 68s 26s
Windows 131s - 175s 63s
MacOS 63s - 76s 28s

Essentially, caching doubles the speed at which bevy_lint can be installed. This is awesome!

Testing

I overhauled our linter-action.yml CI check to test caching. It now tests:

  • When caching is disabled (what we had originally)
  • A cache miss with save-cache-if: 'false'
  • A cache miss with save-cache-if: 'true'
  • A cache hit

Because these tests depend on the global CI cache, I restricted the concurrency of this workflow so only one instance of it can run at a time. This may result in slower CI times when several PRs are merged at the same time or several PRs modify bevy_lint/action.yml, but in practice I don't think that will be an issue.

@BD103 BD103 added A-Build-System Related to CI and GitHub Actions A-Linter Related to the linter and custom lints C-Feature Make something new possible D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Jul 21, 2025
@BD103 BD103 force-pushed the linter-action-caching branch 2 times, most recently from bf3652f to b328396 Compare July 22, 2025 18:44
@BD103 BD103 force-pushed the linter-action-caching branch from b328396 to af02286 Compare July 22, 2025 21:12
@BD103 BD103 marked this pull request as ready for review July 22, 2025 22:23
@BD103 BD103 added S-Needs-Review The PR needs to be reviewed before it can be merged C-Performance and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged C-Feature Make something new possible labels Jul 22, 2025
@@ -8,10 +8,25 @@ on:
paths:
- bevy_lint/action.yml
- rust-toolchain.toml
- .github/workflows/linter-action.yml
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While unrelated, this lets us test linter-action.yml in CI on PRs when linter-action.yml is modified.

Comment on lines 52 to 53
- name: Run `bevy_lint` on `bevy_lint`
run: bevy_lint --package bevy_lint --locked
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose not to run this for all of the other cache jobs in order to speed up the workflow runtime. Instead, the other jobs just run bevy_lint --version.

Let me know if you think I should change this!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what the workflow diagram looks like now:

Image

It's important that the cache-related jobs run sequentially because they depend on the cache existing or not in order to succeed.

If set to `true`, this action will cache the built `bevy_lint` executable and reuse it on
subsequent runs, which can speed up the runtime. This defaults to `false`.
required: false
default: 'false'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is a string and not a boolean. Action inputs are converted to strings, making these two steps equivalent:

- uses: TheBevyFlock/bevy_cli/bevy_lint@main
  with:
    cache: true

- uses: TheBevyFlock/bevy_cli/bevy_lint@main
  with:
    cache: 'true'

This is important when checking if the input is true or false, as non-empty strings are truthy:

if: ${{ true }} # true
if: ${{ 'true' }} # true
if: ${{ false }} # false
if: ${{ '' }} # false
if: ${{ 'false' }} # true! :O

This is why I do a lot of ${{ inputs.cache == 'true' }} instead of just ${{ inputs.cache }}.

Comment on lines +27 to +33
description: |
A string indicating whether an existing cached `bevy_lint` was used. This will be 'true' if a
cache was used and '' (an empty string) if a cache was not. If caching is disabled, this will
always be an empty string.
# Technically `cache-hit` could be 'false' if a fallback key was used instead of the primary
# key, but we don't use fallback keys, so that shouldn't happen.
value: ${{ steps.cache.outputs.cache-hit || steps.restore-cache.outputs.cache-hit }}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I would much rather this be 'true' or 'false' for if the cache was hit, actions/cache uses 'true' and ''. I'd rather follow precedence here than make things confusing and different.

id: cache-key
if: ${{ inputs.cache == 'true' }}
shell: bash
run: echo "key=bevy_lint-${RUNNER_OS}-${ACTION_REF}" >> "${GITHUB_OUTPUT}"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This key makes it so caches for different operating systems and linter versions won't be shared. For example, Windows and MacOS will have separate caches, and bevy_lint v0.3.0 and bevy_lint main will have separate caches.

@BD103 BD103 added C-Testing A change to the tests and removed C-Testing A change to the tests labels Jul 22, 2025
@BD103 BD103 added this to the `bevy_lint` v0.4.0 milestone Jul 23, 2025
@BD103 BD103 linked an issue Jul 23, 2025 that may be closed by this pull request
Copy link
Collaborator

@TimJentzsch TimJentzsch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool, and nicely documented and tested :)

If set to `true`, this action will cache the built `bevy_lint` executable and reuse it on
subsequent runs, which can speed up the runtime. This defaults to `false`.
required: false
default: 'false'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious, if the speedup is so big, why don't we enable caching by default?
I would expect most users wanting to have it enabled.

`bevy_lint` provides an action to conveniently install the linter in CI:
> **Important**
>
> The action is only available for versions v0.3.0 and onward. v0.2.0 and v0.1.0 will not work, however you may emulate it by manually running the [installation commands](install.md) in your workflow.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the long term (and in a separate PR) we should define some sort of shortcut or component to indicate version compatibility in the book, something like "since v0.3.0".

This would also be useful for the CLI!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Build-System Related to CI and GitHub Actions A-Linter Related to the linter and custom lints C-Performance D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review The PR needs to be reviewed before it can be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Linter action doesn't work easily with caching
2 participants