Skip to content
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

[BUG] setup-python fails across multiple Windows and action versions when caching is requested and newer pip outputs a deprecation warning (any really) #1034

Open
2 of 5 tasks
webknjaz opened this issue Feb 13, 2025 · 12 comments
Assignees
Labels
bug Something isn't working

Comments

@webknjaz
Copy link

webknjaz commented Feb 13, 2025

UPD(17.02.2025): To anyone landing here from Google or hitting this bug otherwise

Tip

Here's the solution I landed on, not only because of just this bug, but I've also been wanting better cache control for quite a while, so I've wrapped what I've been copying and pasting for years into a more reusable component — a composite action that can sense whether it's safe to cache things based on the current runtime stability (ABI stability is computed based on the version being marked as final). Feel free to make use of it: https://github.com/re-actors/cache-python-deps.

The sample use would be

- name: Restore pip cache
  uses: re-actors/cache-python-deps@release/v1
  with:
    cache-key-for-dependency-files: >-
      ${{
        hashFiles(
          '.pre-commit-config.yaml',
          'requirements/**',
          'tox.ini',
          'tox.toml',
          'pyproject.toml'
        )
      }}

provided that it's invoked after setup-python and after a sort of checkout (or similar). Integration example: aio-libs/frozenlist#622 / aio-libs/frozenlist#633.

P.S. The root cause of the bug is that setup-python threads any stderr from pip as a failure in any Windows runtimes. New pip started outputting a warning about a CLI flag being deprecated. That CLI flag is often being set via env vars like PIP_NO_PYTHON_VERSION_WARNING (meant to suppress another warning in the output). More explanation here: #1034 (comment).

Description:

I've been updating a few GHA configurations today and in the process saw the same error in several places. Interestingly, in some repos it fails in one workflow but works in another. I've been seeing this for the past few hours, but this is in repos I haven't touched in months, so the issue might've appeared earlier.

I've tried finding differences and similarities, but cannot say anything definitive.

Among the similarities, there's these:

Current runner version: '2.322.0'
Runner Image
  Image: windows-2019
  Version: 20250209.1.0
Runner Image Provisioner
  2.0.422.1

Also, the action fails on both windows-2019 and windows-2022. It fails in matrixes that pass a variety of Python versions, starting with 3.9 and all the way to 3.13.

Another bit I noticed was that some of the jobs downloaded immutable actions, while others fetched from Git. But there's examples of both in failing/passing action invocations.

Failing job examples (there's more in the same workflow runs):

Success example:

As you can see, there's successes and failures in the same repo, just different job definitions.

While writing this, I also noticed that the failing ones have some sort of file preparation before calling setup-python and caching args enabled. Worth checking out... I'll report back once I experiment some more.

Action version:

v5

Platform:

  • Ubuntu
  • macOS
  • Windows

Runner type:

  • Hosted
  • Self-hosted

Tools version:

🤷‍♂ seems to be any Python version and any windows image.

Repro steps:

Add a step with actions/setup-python@v5 into a windows job, set PIP_NO_PYTHON_VERSION_WARNING: 1 env var and add the cache: pip input.

Expected behavior:

It should succeed.

Actual behavior:

The action spits out Error: Could not get cache folder path for pip package manager, after the successful Installed versions output, and crashes the job.

@webknjaz webknjaz added bug Something isn't working needs triage labels Feb 13, 2025
webknjaz added a commit to webknjaz/frozenlist that referenced this issue Feb 13, 2025
This is an experimental attempt to work around the bug in
`actions/setup-python@v5` [[1]].

[1]: actions/setup-python#1034
@webknjaz
Copy link
Author

webknjaz commented Feb 13, 2025

So this experiment shows that dropping the cache inputs makes it pass: aio-libs/frozenlist#622.

@suyashgaonkar
Copy link

Hi @webknjaz ,Thank you for creating this issue. We will investigate it and provide feedback as soon as we have some updates.

@webknjaz
Copy link
Author

webknjaz commented Feb 14, 2025

This is the line that the action hits in the broken scenario:

`Could not get cache folder path for pip package manager`
.

I tried various things so far.

Moving the requirements files mentioned in the cache-dependency-path to the top level of the repo does not help: https://github.com/aio-libs/frozenlist/actions/runs/13328642529/job/37227633874?pr=627#step:4:27. This excludes the possibility of this problem being related to non-normalized path separator (slash vs. backslash).

Moving setup-python before checkout makes it break due to the absence of the req files. This is expected.

Deleting the cache and cache-dependency-path inputs does work. So it's a viable workaround. https://github.com/aio-libs/frozenlist/actions/runs/13315768115/job/37189473317?pr=622#step:4:23

@webknjaz
Copy link
Author

In an attempt to bisect the problem, I tried v5.2.0 (https://github.com/aio-libs/frozenlist/actions/runs/13328934530/job/37228641891?pr=629#step:4:27) and v5.1.0 (https://github.com/aio-libs/frozenlist/actions/runs/13328909086/job/37228544936?pr=628#step:4:27). Both are still broken.

Can the cache be corrupted somehow?

@webknjaz
Copy link
Author

Older action versions are broken the same way:
v5.0.0: https://github.com/aio-libs/frozenlist/actions/runs/13329181570/job/37229342141?pr=630#step:4:27
v4.0.0: https://github.com/aio-libs/frozenlist/actions/runs/13329182488/job/37229360342?pr=631#step:4:26

I wonder if something changed in the recently published CPython builds…

@webknjaz
Copy link
Author

I wonder if something changed in the recently published CPython builds…

Nope... Requesting Python 3.13.0 published a while back (instead of 3.13.2) still results in an error: https://github.com/aio-libs/frozenlist/actions/runs/13329352448/job/37229847658#step:4:165

@webknjaz
Copy link
Author

I thought that manual cache invalidation would help, but when I've gone to delete it in Cheroot, I realized that there's no cache prefixed with setup-python- in that repo. I delete the other manually-managed Windows cache, but it did not do anything.

I've checked frozenlist, and it does have caches prefixed with setup-python- but not with setup-python-Windows-. Can this be another bit of the puzzle? Does the reproducer require that there's no pre-existing cache saved?

webknjaz added a commit to webknjaz/cheroot that referenced this issue Feb 15, 2025
The upstream `actions/setup-python` has rudimentary support for cache
management but it's rather limited. It also has bugs in caching [[1]].

Having own reusable cache computation bit gives us better level of
control, letting us make cache depend on specific Python runtime
features.

[1]: actions/setup-python#1034
webknjaz added a commit to webknjaz/frozenlist that referenced this issue Feb 15, 2025
The upstream `actions/setup-python` has rudimentary support for cache
management but it's rather limited. It also has bugs in caching [[1]].

Having own reusable cache computation bit gives us better level of
control, letting us make cache depend on specific Python runtime
features.

[1]: actions/setup-python#1034
webknjaz added a commit to webknjaz/frozenlist that referenced this issue Feb 15, 2025
The upstream `actions/setup-python` has rudimentary support for cache
management but it's rather limited. It also has bugs in caching [[1]].

Having own reusable cache computation bit gives us better level of
control, letting us make cache depend on specific Python runtime
features.

[1]: actions/setup-python#1034
webknjaz added a commit to webknjaz/frozenlist that referenced this issue Feb 15, 2025
The upstream `actions/setup-python` has rudimentary support for cache
management but it's rather limited. It also has bugs in caching [[1]].

Having own reusable cache computation bit gives us better level of
control, letting us make cache depend on specific Python runtime
features.

[1]: actions/setup-python#1034
webknjaz added a commit to webknjaz/frozenlist that referenced this issue Feb 15, 2025
The upstream `actions/setup-python` has rudimentary support for cache
management but it's rather limited. It also has bugs in caching [[1]].

Having own reusable cache computation bit gives us better level of
control, letting us make cache depend on specific Python runtime
features.

[1]: actions/setup-python#1034
webknjaz added a commit to webknjaz/frozenlist that referenced this issue Feb 15, 2025
The upstream `actions/setup-python` has rudimentary support for cache
management but it's rather limited. It also has bugs in caching [[1]].

Having own reusable cache computation bit gives us better level of
control, letting us make cache depend on specific Python runtime
features.

[1]: actions/setup-python#1034
@webknjaz
Copy link
Author

Reading

let exitCode = 1;
let stdout = '';
let stderr = '';
// Add temporary fix for Windows
// On windows it is necessary to execute through an exec
// because the getExecOutput gives a non zero code or writes to stderr for pip 22.0.2,
// or spawn must be started with the shell option enabled for getExecOutput
// Related issue: https://github.com/actions/setup-python/issues/328
if (IS_WINDOWS) {
const execPromisify = utils.promisify(child_process.exec);
({stdout: stdout, stderr: stderr} = await execPromisify('pip cache dir'));
} else {
({
stdout: stdout,
stderr: stderr,
exitCode: exitCode
} = await exec.getExecOutput('pip cache dir'));
}
if (exitCode && stderr) {
throw new Error(
`Could not get cache folder path for pip package manager`
);
}
, I have a theory of what's happening:

  1. There's exitCode = 1 at the beginning
  2. But the windows branch does not set the return code, so it's always 1.
  3. This means that if (exitCode && stderr) is only influenced by stderr on Windows.
  4. A new release of pip v25.0.1 got published on Feb 9.
  5. By default, pip prints out hints with "hey there's a new version available, wanna upgrade?" on any pip invocations.
  6. So when the action calls pip cache dir, the bundled version of pip is older than the one on PyPI.
  7. On Windows, that gets into stderr but the return code in the variable is not updated — it remains set to 1.

To summarize, this corner case is triggered on Windows but not *NIX, whenever a new version of pip is published to PyPI, but the respective Python build from https://github.com/actions/python-versions ships older pip. That older pip would print upgrade hints, which setup-python would misinterpret as error output on Windows.

This bug has been introduced by #332.

@webknjaz webknjaz changed the title Error: Could not get cache folder path for pip package manager across multiple Windows and action versions today Error: Could not get cache folder path for pip package manager across multiple Windows and action versions when caching is enabled and new pip is published Feb 16, 2025
@webknjaz webknjaz changed the title Error: Could not get cache folder path for pip package manager across multiple Windows and action versions when caching is enabled and new pip is published [BUG] setup-python fails across multiple Windows and action versions when caching is requested and newer pip is published on PyPI Feb 16, 2025
@webknjaz webknjaz changed the title [BUG] setup-python fails across multiple Windows and action versions when caching is requested and newer pip is published on PyPI [BUG] setup-python fails across multiple Windows and action versions when caching is requested and newer pip outputs a deprecation warning (any really) Feb 16, 2025
@webknjaz
Copy link
Author

The only thing I was incorrect about was the warning being output, it seems. It's not the upgrade hint, but a deprecation:

DEPRECATION: --no-python-version-warning is deprecated. pip 25.1 will enforce this behaviour change. A possible replacement is to remove the flag as it's a no-op. Discussion can be found at https://github.com/pypa/pip/issues/13154

@webknjaz
Copy link
Author

To anyone landing here from Google or hitting this bug otherwise

I've been wanting better cache control for quite a while, so I've wrapped what I've been doing for years into a more reusable component — a composite action that can sense whether it's safe to cache things based on the current runtime stability (ABI stability is computed based on the version being marked as final). Feel free to make use of it: https://github.com/re-actors/cache-python-deps.

The sample use would be

- name: Restore pip cache
  uses: re-actors/cache-python-deps@release/v1
  with:
    cache-key-for-dependency-files: >-
      ${{
        hashFiles(
          '.pre-commit-config.yaml',
          'requirements/**',
          'tox.ini',
          'tox.toml',
          'pyproject.toml'
        )
      }}

provided that it's invoked after setup-python and after a sort of checkout (or similar).

@priyagupta108
Copy link
Contributor

Hello @webknjaz , thank you for the detailed report.
The issue arises from the --no-python-version-warning flag, which has become redundant and is no longer functional. This flag now triggers a warning to stderr from pip, leading to the failure. We are continuing our investigation into the matter.

As an immediate workaround, we recommend removing the PIP_NO_PYTHON_VERSION_WARNING environment variable. This will prevent the warning from being output to stderr, allowing your workflow to proceed without errors.

Alternatively, for Windows environments, you can use the actions/cache action after the setup-python action to manage caching. For more details, you can refer to the actions/cache documentation. Here is an example configuration:

- name: Cache pip dependencies
  uses: actions/cache@v4
  with:
   path: ~\AppData\Local\pip\Cache
   key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
   restore-keys: |
     ${{ runner.os }}-pip-

@webknjaz
Copy link
Author

@priyagupta108 yes, I know. I'm using it like that. Just made a wrapper action to abstract away a few other caching quirks better that setup-python doesn't implement anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants