Keep package directories accessible under restrictive build umasks
Release / release (push) Successful in 1m14s
Release / release (push) Successful in 1m14s
This commit is contained in:
@@ -21,6 +21,7 @@ backfill releases from before this changelog.
|
||||
- Preserve historical selections and store-fault messages through graph refresh and resize.
|
||||
- Show hourly drill-down results without overwriting them with a loading placeholder.
|
||||
- Keep known unallocated daily volume visible across coverage gaps, and distinguish missing hourly evidence from zero on small terminals.
|
||||
- Stage package directories with consistent public permissions, avoiding openSUSE RPM conflicts and inaccessible runtime paths when built with a restrictive umask.
|
||||
|
||||
## [0.4.0] - 2026-09-18
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
# /usr/lib/tmpfiles.d/fenris.conf
|
||||
set -euo pipefail
|
||||
|
||||
# Package directories must be traversable by every runtime user and agree
|
||||
# with distribution-owned directories, regardless of the builder's umask.
|
||||
umask 022
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
STAGE_DIR="${REPO_ROOT}/build/stage"
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
"""Package directory permissions must not inherit a builder's private umask."""
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mask", ["077", "022"])
|
||||
def test_stage_is_publicly_traversable_under_any_builder_umask(tmp_path, mask):
|
||||
root = Path(__file__).resolve().parent.parent
|
||||
for directory in ("packaging", "scripts", "src", "units", "polkit"):
|
||||
shutil.copytree(root / directory, tmp_path / directory,
|
||||
ignore=shutil.ignore_patterns("__pycache__", "*.egg-info"))
|
||||
for filename in ("LICENSE", "requirements.txt"):
|
||||
shutil.copy(root / filename, tmp_path / filename)
|
||||
(tmp_path / "dist").mkdir()
|
||||
(tmp_path / "dist/fenris-9.9.9-py3-none-any.whl").touch()
|
||||
bin_dir = tmp_path / "bin"
|
||||
bin_dir.mkdir()
|
||||
# Avoid downloading dependencies: emulate pip's target output while
|
||||
# exercising the real staging script and its package directory layout.
|
||||
pip_stub = bin_dir / "python3"
|
||||
pip_stub.write_text(
|
||||
f"#!{sys.executable}\n"
|
||||
"import sys\nfrom pathlib import Path\n"
|
||||
"target = Path(sys.argv[sys.argv.index('--target') + 1]) / 'fenris'\n"
|
||||
"target.mkdir(parents=True)\n"
|
||||
"(target / '__init__.py').write_text('')\n"
|
||||
)
|
||||
pip_stub.chmod(0o755)
|
||||
subprocess.run(
|
||||
["bash", "-c", f"umask {mask}; exec bash packaging/stage.sh 9.9.9"],
|
||||
cwd=tmp_path, env={**os.environ, "PATH": str(bin_dir) + os.pathsep + os.environ["PATH"]},
|
||||
check=True, capture_output=True, text=True,
|
||||
)
|
||||
stage = tmp_path / "build/stage"
|
||||
for directory in (stage, *(p for p in stage.rglob("*") if p.is_dir())):
|
||||
assert directory.stat().st_mode & 0o777 == 0o755, directory
|
||||
assert (stage / "usr/bin/fenris").stat().st_mode & 0o777 == 0o755
|
||||
assert (stage / "opt/fenris/vendor/fenris/__init__.py").stat().st_mode & 0o444 == 0o444
|
||||
Reference in New Issue
Block a user