v30.3-roots.1 · Commit 68: [PATCH 68/68] fix(release): stage Linux license in Docker-owned output
ci/test/test_prepare_release.py
Before: ci/test/test_prepare_release.py · After: ci/test/test_prepare_release.py
File metadata
index 5ed09a1fd970db7e5329d7c4ad7d02c9167c30eb..eefc00275c41480c3e1b45768881746ec3d59b15 100755
Download original patch · Release notes
Diff rows 1–42 of 42. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
ci/test/test_prepare_release.py
CHANGED
|
@@ -129,6 +129,30 @@ class PrepareReleaseTest(unittest.TestCase):
|
|
| 129 |
"RELEASE_TAG": "v30.3-roots.1", "GITHUB_WORKSPACE": str(work)}
|
| 130 |
if platform.startswith("linux"):
|
| 131 |
(out / "payload").write_bytes(b"binary fixture")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
block = packaging_block("Package release artifacts")
|
| 133 |
else:
|
| 134 |
deploy = work / "ci/scratch/build-fixture"
|
|
@@ -148,6 +172,12 @@ class PrepareReleaseTest(unittest.TestCase):
|
|
| 148 |
notice = package.read(member)
|
| 149 |
self.assertEqual(package.read("bitcoin-roots-30.3-roots.1/Bitcoin-Qt.app/Contents/MacOS/Bitcoin-Qt"), b"binary fixture")
|
| 150 |
self.assertEqual(notice, (ROOT / "COPYING").read_bytes())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
downloads = work / "assembled-downloads"
|
| 152 |
downloads.mkdir()
|
| 153 |
assembled = downloads / archive.name
|
|
|
|
| 129 |
"RELEASE_TAG": "v30.3-roots.1", "GITHUB_WORKSPACE": str(work)}
|
| 130 |
if platform.startswith("linux"):
|
| 131 |
(out / "payload").write_bytes(b"binary fixture")
|
| 132 |
+
# Model the non-writable Docker-owned mount. Privilege
|
| 133 |
+
# escalation is unavailable locally; this narrow sudo
|
| 134 |
+
# fixture grants write access only around the command.
|
| 135 |
+
out.chmod(0o555)
|
| 136 |
+
if os.geteuid() != 0:
|
| 137 |
+
denied = subprocess.run(["python3", ARCHIVE_TOOL, "stage-copying", out],
|
| 138 |
+
capture_output=True, text=True)
|
| 139 |
+
self.assertNotEqual(denied.returncode, 0)
|
| 140 |
+
self.assertIn("Permission denied", denied.stderr)
|
| 141 |
+
tools = work / "tools"
|
| 142 |
+
tools.mkdir()
|
| 143 |
+
sudo = tools / "sudo"
|
| 144 |
+
sudo.write_text('#!/usr/bin/env bash\nset -Eeuo pipefail\n'
|
| 145 |
+
'printf "%s\\n" "$@" > "$SUDO_RECORD"\n'
|
| 146 |
+
'test "$#" -eq 4\n'
|
| 147 |
+
'test "$1" = python3\n'
|
| 148 |
+
'test "$2" = ci/release/archive.py\n'
|
| 149 |
+
'test "$3" = stage-copying\n'
|
| 150 |
+
'chmod u+w "$4"\n'
|
| 151 |
+
"trap 'chmod u-w \"$4\"' EXIT\n"
|
| 152 |
+
'"$@"\n')
|
| 153 |
+
sudo.chmod(0o755)
|
| 154 |
+
environment.update(PATH=f"{tools}:{os.environ['PATH']}",
|
| 155 |
+
SUDO_RECORD=str(work / "sudo-record"))
|
| 156 |
block = packaging_block("Package release artifacts")
|
| 157 |
else:
|
| 158 |
deploy = work / "ci/scratch/build-fixture"
|
|
|
|
| 172 |
notice = package.read(member)
|
| 173 |
self.assertEqual(package.read("bitcoin-roots-30.3-roots.1/Bitcoin-Qt.app/Contents/MacOS/Bitcoin-Qt"), b"binary fixture")
|
| 174 |
self.assertEqual(notice, (ROOT / "COPYING").read_bytes())
|
| 175 |
+
if platform.startswith("linux"):
|
| 176 |
+
self.assertEqual((work / "sudo-record").read_text().splitlines(),
|
| 177 |
+
["python3", "ci/release/archive.py", "stage-copying", str(out)])
|
| 178 |
+
self.assertEqual(out.stat().st_mode & 0o777, 0o555)
|
| 179 |
+
# Permit fixture cleanup, preserving the archived mode.
|
| 180 |
+
out.chmod(0o755)
|
| 181 |
downloads = work / "assembled-downloads"
|
| 182 |
downloads.mkdir()
|
| 183 |
assembled = downloads / archive.name
|