Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions apps/maple-agent/scripts/build-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ if [[ ${#target_args[@]} != 0 ]]; then
fi
python3 "$component/scripts/generate-third-party-notices.py"
binary="$component/target/release/maple-agent"
case "$(uname -s)" in MINGW*|MSYS*|CYGWIN*) binary="${binary}.exe" ;; esac
"$binary" --build-info |
python3 -c 'import json,sys; info=json.load(sys.stdin); expected=sys.argv[1]; assert info["profile"] == expected, "incorrect release profile"' "$1"
case "$(uname -s)" in
MINGW*|MSYS*|CYGWIN*)
# The unsigned prebuilt Windows bootstrap is not an installed app.
# Validate its immutable PE metadata without entering runtime trust or
# installation checks; signing and installed-app smoke happen later.
python3 "$component/scripts/windows-build-info.py" "${binary}.exe" \
--profile "$1" --source-sha "$(git rev-parse HEAD)" >/dev/null
;;
*)
"$binary" --build-info |
python3 -c 'import json,sys; info=json.load(sys.stdin); expected=sys.argv[1]; assert info["profile"] == expected, "incorrect release profile"' "$1"
;;
esac
122 changes: 122 additions & 0 deletions apps/maple-agent/scripts/test_release_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import unittest
from test_macos_build_info import macho
from test_third_party_notices import notice_fixture
from test_windows_build_info import pe, public_info as windows_info


SCRIPTS = Path(__file__).resolve().parent
Expand Down Expand Up @@ -170,6 +171,127 @@ def test_downloaded_binary_must_be_a_regular_file(self):
self.assertEqual(target.stat().st_mode & 0o777, 0o644)


@unittest.skipUnless(os.name == "posix", "hermetic shell fixture requires a POSIX host")
class BuildReleaseMetadataTests(unittest.TestCase):
def setUp(self):
temporary = tempfile.TemporaryDirectory()
self.addCleanup(temporary.cleanup)
self.component = Path(temporary.name) / "component with spaces"
scripts = self.component / "scripts"
scripts.mkdir(parents=True)
for name in ("build-release.sh", "windows-build-info.py", "release-info.py"):
shutil.copy2(SCRIPTS / name, scripts / name)
shutil.copy2(SCRIPTS.parent / "release-profiles.json", self.component)
(scripts / "generate-third-party-notices.py").write_text(
"from pathlib import Path\nPath('notices-generated').write_text('called')\n"
)
self.env = dict(os.environ, GIT_CONFIG_GLOBAL=os.devnull, GIT_CONFIG_NOSYSTEM="1")
for arguments in (("init", "--quiet"), ("add", "."),
("-c", "user.name=Fixture", "-c", "user.email=fixture@example.invalid",
"-c", "commit.gpgsign=false", "-c", "core.hooksPath=/dev/null",
"commit", "--quiet", "-m", "fixture source")):
subprocess.run(["git", "-C", str(self.component), *arguments], env=self.env,
check=True, capture_output=True, text=True)
self.source = subprocess.check_output(
["git", "-C", str(self.component), "rev-parse", "HEAD"], env=self.env, text=True,
).strip()
self.input = self.component / "fixture-binary"
self.metadata = self.component / "fixture-info.json"
self.executed = self.component / "fixture-executed"
self.commands = self.component / "cargo-commands.jsonl"
tools = self.component / "tools"
tools.mkdir()
for name, source in {
"uname": "import os\nprint(os.environ['FIXTURE_OS'])\n",
"cargo": """import json, os, shutil, sys
from pathlib import Path
arguments = sys.argv[1:]
with Path(os.environ['FIXTURE_COMMANDS']).open('a') as log:
log.write(json.dumps(arguments) + '\\n')
if arguments == ['fetch', '--locked']:
sys.exit(0)
windows = os.environ['FIXTURE_OS'].startswith(('MINGW', 'MSYS', 'CYGWIN'))
expected = ['build', '--release', '-p', 'maple-agent-app', '--locked', '--timings']
if windows:
expected += ['--target', 'x86_64-pc-windows-msvc']
assert arguments == expected, arguments
target = Path('target/x86_64-pc-windows-msvc/release/maple-agent.exe' if windows else 'target/release/maple-agent')
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copyfile(os.environ['FIXTURE_INPUT'], target)
target.chmod(0o644 if windows else 0o755)
""",
}.items():
tool = tools / name
tool.write_text(f"#!{sys.executable}\n" + source)
tool.chmod(0o755)
self.env.update(PATH=str(tools) + os.pathsep + self.env["PATH"],
FIXTURE_INPUT=str(self.input), FIXTURE_COMMANDS=str(self.commands),
FIXTURE_METADATA=str(self.metadata), FIXTURE_EXECUTED=str(self.executed))

def build(self, operating_system, profile="dev"):
self.env["FIXTURE_OS"] = operating_system
result = subprocess.run(["bash", str(self.component / "scripts/build-release.sh"), profile],
env=self.env, capture_output=True, text=True)
self.assertEqual((self.component / "notices-generated").read_text(), "called")
return result

def test_windows_build_checks_the_staged_pe_without_executing_it(self):
for operating_system in ("MINGW64_NT-10.0", "MSYS_NT-10.0", "CYGWIN_NT-10.0"):
for profile in ("dev", "prod"):
with self.subTest(operating_system=operating_system, profile=profile):
expected = pe(windows_info(profile, self.source))
self.input.write_bytes(expected)
self.input.chmod(0o644)
# This genuine metadata-only PE cannot execute on the
# portable fixture host. Success must come from parsing.
with self.assertRaises(OSError):
subprocess.run([str(self.input), "--build-info"], check=True)
result = self.build(operating_system, profile)
self.assertEqual(result.returncode, 0, result.stderr)
staged = self.component / "target/release/maple-agent.exe"
self.assertEqual(staged.read_bytes(), expected)
self.assertEqual(staged.stat().st_mode & 0o777, 0o644)
commands = [json.loads(line) for line in self.commands.read_text().splitlines()]
self.assertEqual(len(commands), 12)
self.assertEqual(commands[::2], [["fetch", "--locked"]] * 6)

def test_windows_build_rejects_wrong_profile_source_and_dirty_revision(self):
for profile in ("dev", "prod"):
wrong_profile = "prod" if profile == "dev" else "dev"
for identity, error in (
(windows_info(wrong_profile, self.source), "release profile"),
(windows_info(profile, "b" * 40), "source commit"),
({**windows_info(profile, self.source), "git_revision": self.source[:8] + "-dirty"}, "revision"),
):
with self.subTest(profile=profile, error=error):
self.input.write_bytes(pe(identity))
result = self.build("MINGW64_NT-10.0", profile)
self.assertNotEqual(result.returncode, 0)
self.assertIn(error, result.stderr)
self.assertIn("static Windows build-info validation failed", result.stderr)

def test_macos_and_linux_keep_executing_the_existing_build_info_cli(self):
self.input.write_text(f"#!{sys.executable}\n" + """import json, os, sys
from pathlib import Path
assert sys.argv[1:] == ['--build-info']
Path(os.environ['FIXTURE_EXECUTED']).write_text(json.dumps(sys.argv[1:]))
print(Path(os.environ['FIXTURE_METADATA']).read_text())
""")
for operating_system in ("Darwin", "Linux"):
for profile in ("dev", "prod"):
for reported in ("dev", "prod"):
with self.subTest(operating_system=operating_system, requested=profile, reported=reported):
self.executed.unlink(missing_ok=True)
self.metadata.write_text(json.dumps({"profile": reported}))
result = self.build(operating_system, profile)
self.assertEqual(json.loads(self.executed.read_text()), ["--build-info"])
if reported == profile:
self.assertEqual(result.returncode, 0, result.stderr)
else:
self.assertNotEqual(result.returncode, 0)
self.assertIn("incorrect release profile", result.stderr)


class LinuxVerifierExtractionTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
Expand Down
Loading