Skip to content

👷 Optimize cache usage in workflows - #16152

Open
YuriiMotov wants to merge 19 commits into
masterfrom
optimize-workflow-cache
Open

👷 Optimize cache usage in workflows#16152
YuriiMotov wants to merge 19 commits into
masterfrom
optimize-workflow-cache

Conversation

@YuriiMotov

@YuriiMotov YuriiMotov commented Aug 7, 2026

Copy link
Copy Markdown
Member

Description

After upgrading https://github.com/astral-sh/setup-uv to 9.0.0 it started saving downloaded wheels to cache (prune-cache is now false by default).

But there are currently several things that make caching less efficient:

  • Some workflows install deps with --no-dev but don't use UV_NO_SYNC: false, so uv run still installs dev dependencies and caches them
  • ~15 jobs shared the same cache key, but installed different set of dependencies. It might introduce a race - different cache content depending on what job finished first
  • Workflows triggered by pull_request still save cache, but this cache is scoped to merge branch and can't be read by others
  • regression-test job always has cache miss because it copies project from the base branch into base/ and cache-dependency-glob uses all projects to compute the hash by default

This PR introduces several cache key suffixes with different set of dependencies, and ensures that there is at least one job for each cache key that writes cache to default branch scope, so that other workflows would be able to read it.

Cache key suffixes:

  • dev-all:
    • Content: --group dev --extra all
    • Writers: warm-cache.yml (default-branch scoped), pre-commit.yml (PR-branch scoped, only available to this PR)
    • Readers: pre-commit.yml, bump-pre-commit-hooks.yml, create-draft-release.yml, prepare-release.yml
    • Comment: we need warm-cache.yml because pre-commit.yml runs on pull_request and can only write cache scoped to PR branch (others can't read), and other workflows run not regularly and can't keep cache warm
  • docs:
    • Content: --group docs
    • Writers and readers: build-docs.yml (writes to default branch scope on push to master branch, so that all other runs can read it)
  • github-actions:
    • Content: --group github-actions
    • Writers and readers: label-approved.yml, notify-translations.yml, smokeshow.yml, sponsors.yml, topic-repos.yml, translate.yml
  • tests-highest:
    • Content: --group tests --extra all
    • Writers:: matrix items of test job in test.yml except those that use lowest-direct (writes to default branch scope on push to master branch, so that all other runs can read it)
    • Readers: all jobs in test.yml except those that use lowest-direct
  • tests-lowest-direct:
    • Content: --group tests --extra all resolved with UV_RESOLUTION=lowest-direct
    • Writers and readers: matrix items of test job in test.yml that use lowest-direct (writes to default branch scope on push to master branch, so that all other runs can read it)
  • translations:
    • Content: --group github-actions --group translations
    • Writers: langs job
    • Readers: matrix items of translate job

AI Disclaimer

Used Claude Code (Opus 5) to investigate and implement the fix. Checked manually

Checklist

  • This PR links to a GitHub Discussion for the proposed code change.
  • I added tests for the change.
  • The new or updated tests fail on the main branch and pass on this PR.
  • Coverage stays at 100%.
  • The documentation explains the change if needed.

@YuriiMotov YuriiMotov added the internal Internal changes label Aug 7, 2026
@codspeed-hq

codspeed-hq Bot commented Aug 7, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing optimize-workflow-cache (ff6a7c0) with master (c567218)1

Open in CodSpeed

Footnotes

  1. No successful run was found on master (4903347) during the generation of this report, so c567218 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

📝 Docs preview

Last commit ff6a7c0 at: https://9dad2be2.fastapitiangolo.pages.dev

This comment was marked as resolved.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Comment on lines +9 to +10
env:
UV_NO_SYNC: true

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Without this, it would skip installing dev group on uv sync --locked --no-dev --group docs, but still install it later on uv run ./scripts/docs.py build-lang ${{ matrix.lang }} and then cache it.
The same in other workflows

Comment on lines +262 to +264
cache-dependency-glob: |
base/pyproject.toml
base/uv.lock

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We need to use project from base/. By default it would compute the hash on all projects (root directory and base/ directory)

Comment thread .github/workflows/pre-commit.yml Outdated
@YuriiMotov
YuriiMotov marked this pull request as ready for review August 7, 2026 10:51
@github-actions

This comment was marked as resolved.

@github-actions github-actions Bot added the conflicts Automatically generated when a PR has a merge conflict label Aug 8, 2026
@github-actions github-actions Bot removed the conflicts Automatically generated when a PR has a merge conflict label Aug 10, 2026
@github-actions github-actions Bot added the conflicts Automatically generated when a PR has a merge conflict label Aug 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This pull request has a merge conflict that needs to be resolved.

Comment on lines +40 to +42
cache-suffix: dev-all
# Disable saving cache as we install narrower set of dependencies than dev-all has.
save-cache: false

@YuriiMotov YuriiMotov Aug 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This workflow only needs prek installed.
We can add a dependency group with just prek, use it here and disable cache. But dev-all is always warm (see warm-cache workflow), so I decided to reuse it instead and just disabled saving.

Comment on lines +43 to +44
- name: Install dependencies
run: uv sync --locked --group dev

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Added explicit dependency install steps so that it would be clear what dependencies are used by the job

uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
version: "latest-known"
cache-suffix: github-actions

@YuriiMotov YuriiMotov Aug 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Suggested change
cache-suffix: github-actions
cache-suffix: github-actions
enable-cache: true

Since setup-uv v10.0.0, cache for this workflow is disabled (it's triggered by workflow_run) - see release notes.

I think we can safely enable it - we use workflow_run trigger with caution:

  • No checkout of untrusted branches
  • Artifacts used safely (just uploading)
  • Narrow permissions (only statuses: write)
  • No unpinned dependencies
  • We use Zizmor to ensure workflow security
  • Nothing untrusted can write the cache that this job restores

We can also consider disabling Smokeshow workflow temporary for FastAPI repo as it always fails due to upload limits.

with:
version: "latest-known"
enable-cache: true
cache-suffix: tests-${{ matrix.uv-resolution }}

@YuriiMotov YuriiMotov Aug 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We need to include matrix.uv-resolution into cache key in order to prevent possible future collisions if we have two equal matrix items with only difference in uv-resolution.

See: https://github.com/astral-sh/setup-uv#should-i-include-the-resolution-strategy-in-the-cache-key

base/pyproject.toml
base/uv.lock
# Only ever runs on pull requests, so anything it saved would be PR-scoped and useless.
save-cache: false

@YuriiMotov YuriiMotov Aug 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

regression-test only runs on pull requests, so anything it saved would be PR-scoped and useless. But it will still use cache written by other jobs

@github-actions github-actions Bot removed the conflicts Automatically generated when a PR has a merge conflict label Aug 26, 2026
Comment on lines +3 to +5
# Populates the `dev-all` uv cache at default-branch scope so that it could be used by
# `pre-commit.yml` (it has `pull_request` trigger and can't write cache available across PRs)
# and some others that use subset of dev dependencies.

@YuriiMotov YuriiMotov Aug 26, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Other workflows can't write this cache (for dev-all key) because they are either PR-scoped or run too rarely.
This workflow will run every day to ensure dev-all cache is warm and frequently running pre-commit workflow can use it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

internal Internal changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants