Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

`_testing._sourcetests`: shared repo-kind tests assume the `datafiles` fixture copy is writable, which breaks when package data is installed read-only

Aperta
#2,196 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
74/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
testing-qa

Direzione di ricerca

Start in buildstream/_testing/_sourcetests/utils.py at add_plugins_conf, then inspect the shared helpers used by the failing tests in build_checkout.py, fetch.py, mirror.py, track.py, and workspace.py. Reproduce with pytest-datafiles 3.x and read-only package data; done means the listed repo-kind tests pass without PermissionError when their copied trees inherit read-only permissions.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

[!NOTE]
This report comes out of my own personal effort to package buildstream/
buildstream-plugins for nixpkgs (https://github.com/NixOS/nixpkgs/pull/510073) —
it isn't related to or filed on behalf of my employer. Root-causing this and
drafting this report was done with the assistance of an AI coding agent (Claude
Code); I've reviewed the analysis and reproduction myself and stand behind it.

Summary

The shared cross-VCS ("repo kind") test suite in buildstream/_testing/_sourcetests/
(consumed by downstream source plugins via sourcetests_collection_hook, e.g. from
buildstream-plugins) writes new files into the directory tree that pytest's
datafiles fixture (from the pytest-datafiles plugin) copies out for each test.

This assumes the copy is always writable. That assumption broke as a side effect of
an intentional, correct fix in pytest-datafiles 3.0: it now preserves the source
file/directory permission bits on copy (see omarkohl/pytest-datafiles#11, closed with
a regression test to lock in the behaviour). If the source data — i.e. buildstream's
own installed _testing/_sourcetests package data — ends up on disk without the
write bit (for example because it was installed by a package manager that makes
installed files read-only, or, as in our case, because it lives in the Nix store,
where all installed files are always mode 444/dirs 555), every copy datafiles
produces inherits that missing write bit. Any test helper that then tries to write a
new file into that copy fails with PermissionError.

This isn't Nix-specific in principle — it will reproduce in any environment where
buildstream's installed test-data files are non-writable — but Nix's packaging
convention (all store paths are always read-only) makes it 100% reproducible there.

Where we hit it

Packaging buildstream-plugins 2.8.0 for nixpkgs
(https://github.com/apache/buildstream-plugins), whose tests/conftest.py pulls in
the shared suite via:

from buildstream._testing import sourcetests_collection_hook

Running the resulting pytest suite against buildstream 2.8.1 (installed read-only, as
all Nix store paths are) produces 48 errors, all PermissionError, spread across
every parametrized [bzr]/[git] case in:

  • _sourcetests/build_checkout.py::test_fetch_build_checkout
  • _sourcetests/fetch.py::test_fetch, test_fetch_cross_junction
  • _sourcetests/mirror.py::test_mirror_fetch, test_mirror_fetch_upstream_absent,
    test_mirror_from_includes, test_mirror_track_upstream_present,
    test_mirror_track_upstream_absent
  • _sourcetests/track.py::test_track, test_track_recurse,
    test_track_recurse_except, test_cross_junction, test_track_include,
    test_track_include_junction, test_track_junction_included
  • _sourcetests/workspace.py::test_open

Example traceback

request = <SubRequest 'kind' for <Function test_fetch_build_checkout[bzr-strict]>>
datafiles = PosixPath('/build/source/tmp/test_fetch_build_checkout_bzr_0')

    @pytest.fixture(params=ALL_REPO_KINDS.keys())
    def kind(request, datafiles):
        # Register plugins both on the toplevel project and on its junctions
        for project_dir in [str(datafiles), os.path.join(str(datafiles), "files", "sub-project")]:
>           add_plugins_conf(project_dir, request.param)

.../buildstream/_testing/_sourcetests/utils.py:49:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

.../buildstream/_testing/_sourcetests/utils.py:77: in add_plugins_conf
    _yaml.roundtrip_dump(project_conf, project_conf_file)
src/buildstream/_yaml.pyx:477: in buildstream._yaml.roundtrip_dump
    ???
.../lib/python3.14/contextlib.py:141: in __enter__
    return next(self.gen)
.../buildstream/utils.py:663: in save_file_atomic
    fd, tempname = tempfile.mkstemp(dir=tempdir)
.../lib/python3.14/tempfile.py:354: in mkstemp
    return _mkstemp_inner(dir, prefix, suffix, flags, output_type)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

dir = '/build/source/tmp/test_fetch_build_checkout_bzr_0/files/sub-project'

    def _mkstemp_inner(dir, pre, suf, flags, output_type):
        ...
        for seq in range(TMP_MAX):
            name = next(names)
            file = _os.path.join(dir, pre + name + suf)
            _sys.audit("tempfile.mkstemp", file)
            try:
>               fd = _os.open(file, flags, 0o600)
E               PermissionError: [Errno 13] Permission denied: '/build/source/tmp/test_fetch_build_checkout_bzr_0/files/sub-project/tmpb55t9_sb'

.../lib/python3.14/tempfile.py:255: PermissionError

The same shape of failure (write into a datafiles-provided directory that inherited
a non-writable source) recurs across all 48 failing tests listed above — they all
go through add_plugins_conf or an equivalent "write a new file into the copied
project tree" step.

Why this only shows up now

Per omarkohl/pytest-datafiles#11, prior to pytest-datafiles 3.0 the datafiles
fixture did not preserve source permission bits when copying (using py.path),
so a non-writable source always produced a writable copy — masking this bug. 3.0
switched to pathlib/shutil.copy/shutil.copytree, which preserve mode bits by
default, and that change was intentional (a regression test was added specifically
to keep permissions preserved going forward). So pytest-datafiles is behaving
exactly as intended; the bug is in the assumption made on the consuming side, inside
buildstream's own shared test helpers.

Suggested fix

In add_plugins_conf (and any other shared _sourcetests helper that writes into a
datafiles-provided path), don't assume the copy is writable — e.g. chmod the
relevant directory (or just its parent) to be owner-writable before writing into it,
rather than relying on the datafiles copy's permissions matching the installed
package data's permissions.

Environment

  • buildstream 2.8.1
  • buildstream-plugins 2.8.0
  • pytest-datafiles 3.0.1
  • pytest (via nixpkgs' pytestCheckHook)
  • Reproduced via nixpkgs (nix-build -A python314Packages.buildstream-plugins),
    where /nix/store paths are always installed read-only (mode 444 for files, 555
    for directories) — https://github.com/NixOS/nixpkgs/pull/510073
Lingua principale
Python
Stelle
153
Fork
50
Merge medio
1g 34m
PR unite (30g)
4

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/buildstream

Tutte le issue di apache/buildstream

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.