From 03f7a7f5ecc1a410a952bc8fb165fb280d0bca61 Mon Sep 17 00:00:00 2001 From: Alejandro R Mosteo Date: Mon, 4 Sep 2023 12:02:37 +0200 Subject: [PATCH] Add crate environment to build hash inputs (#1432) * Add crate-modified env vars to hash input * Test environment hashing --- src/alire/alire-builds-hashes.adb | 66 +++++++++++++------ .../cr/crate_real/crate_real-1.0.0.toml | 11 ++++ .../tests/build/hashes/hashing-inputs/test.py | 28 ++++---- .../dockerized/misc/default-cache/test.py | 7 +- 4 files changed, 79 insertions(+), 33 deletions(-) diff --git a/src/alire/alire-builds-hashes.adb b/src/alire/alire-builds-hashes.adb index 5bc120eb..27f532f9 100644 --- a/src/alire/alire-builds-hashes.adb +++ b/src/alire/alire-builds-hashes.adb @@ -110,16 +110,22 @@ package body Alire.Builds.Hashes is Backup => False); end Write_Inputs; - begin - Trace.Debug (" build hashing: " & Rel.Milestone.TTY_Image); + ----------------- + -- Add_Profile -- + ----------------- + + procedure Add_Profile is + begin + Add ("profile", + Rel.Name.As_String, + Root.Configuration.Build_Profile (Rel.Name)'Image); + end Add_Profile; - -- Build profile - Add ("profile", - Rel.Name.As_String, - Root.Configuration.Build_Profile (Rel.Name)'Image); + ------------------- + -- Add_Externals -- + ------------------- - -- GPR externals - declare + procedure Add_Externals is Externals : constant Releases.Externals_Info := Rel.GPR_Externals; begin for Var of GPR.Name_Vector'(Externals.Declared @@ -139,22 +145,44 @@ package body Alire.Builds.Hashes is Add ("external", Var, "default"); end if; end loop; - end; - - -- Environment variables - -- TBD + end Add_Externals; - -- Configuration variables - -- TBD + ------------------ + -- Add_Compiler -- + ------------------ - -- Compiler version. Changing compiler will result in incompatible - -- ALI files and produce rebuilds, so it must be part of the hash. - -- Incidentally, this serves to separate by cross-target too. - declare + procedure Add_Compiler is + -- Compiler version. Changing compiler will result in incompatible + -- ALI files and produce rebuilds, so it must be part of the hash. + -- Incidentally, this serves to separate by cross-target too. Compiler : constant Releases.Release := Root.Compiler; begin Add ("version", Compiler.Name.As_String, Compiler.Version.Image); - end; + end Add_Compiler; + + --------------------- + -- Add_Environment -- + --------------------- + + procedure Add_Environment is + begin + for Var of Rel.Environment (Root.Environment) loop + -- If the crate modifies the var, it must be in the loaded env + Add ("environment", Var.Name, Env (Var.Name)); + end loop; + end Add_Environment; + + begin + Trace.Debug (" build hashing: " & Rel.Milestone.TTY_Image); + + -- Add individual contributors to the hash input + Add_Profile; + Add_Externals; + Add_Environment; + Add_Compiler; + + -- Configuration variables + -- TBD -- Dependencies recursive hash? Since a crate can use a dependency -- config spec, it is possible in the worst case for a crate to diff --git a/testsuite/fixtures/toolchain_index/cr/crate_real/crate_real-1.0.0.toml b/testsuite/fixtures/toolchain_index/cr/crate_real/crate_real-1.0.0.toml index 4bfc56aa..27fa5055 100644 --- a/testsuite/fixtures/toolchain_index/cr/crate_real/crate_real-1.0.0.toml +++ b/testsuite/fixtures/toolchain_index/cr/crate_real/crate_real-1.0.0.toml @@ -4,6 +4,17 @@ version = "1.0.0" maintainers = ["alejandro@mosteo.com"] maintainers-logins = ["mylogin"] +# Externals and environment used to track build hash generation immutability + +[gpr-externals] +foo = "" + +[gpr-set-externals] +bar = "foo" + +[environment] +BAZ.set = "foo" + [origin] url = "file:../../../crates/libhello_1.0.0.tgz" hashes = ["sha512:99fa3a55540d0655c87605b54af732f76a8a363015f183b06e98aa91e54c0e69397872718c5c16f436dd6de0fba506dc50c66d34a0e5c61fb63cb01fa22f35ac"] diff --git a/testsuite/tests/build/hashes/hashing-inputs/test.py b/testsuite/tests/build/hashes/hashing-inputs/test.py index ca22cded..88979f81 100644 --- a/testsuite/tests/build/hashes/hashing-inputs/test.py +++ b/testsuite/tests/build/hashes/hashing-inputs/test.py @@ -1,11 +1,12 @@ """ -Test that the inputs to the hashing properly reflect the build profile +Test that the inputs to the hashing properly reflect the build profile and +other inputs. """ import shutil -from drivers.alr import alr_with, init_local_crate, run_alr +from drivers.alr import alr_with, external_compiler_version, init_local_crate, run_alr from drivers.builds import find_hash, hash_input -from drivers.asserts import assert_match +from drivers.asserts import assert_eq, assert_match from drivers import builds run_alr("config", "--set", "--global", "dependencies.shared", "true") @@ -29,15 +30,18 @@ assert_match(".*profile:libhello=VALIDATION.*", # Check that the hashes are different assert hash1 != hash2, "Hashes should be different" -# Chech that the hash inputs contains GPR externals -# either set or observed by the crate: - -assert_match( - ".*external:TEST_FREEFORM_UNSET=default.*" # a declared unset external - ".*external:TEST_GPR_EXTERNAL=gpr_ext_B.*" # a declared & set enum external - ".*external:TEST_UNDECLARED=used_by_another_crate.*", - # set without prev declaration +# Chech that the hash inputs contains exactly what we expect it to contain. +# This includes environment variables, GPR externals set or observed, build +# profile, compiler version. + +assert_eq( + 'environment:TEST_ENV=myenv\n' # plain env var set + 'external:TEST_FREEFORM_UNSET=default\n' # declared unset GPR external + 'external:TEST_GPR_EXTERNAL=gpr_ext_B\n' # declared set GPR external + 'external:TEST_UNDECLARED=used_by_another_crate\n' # modified GPR external + 'profile:libhello=VALIDATION\n' # build profile + f'version:gnat_external={external_compiler_version()}\n', + # compiler version hash_input("libhello")) - print("SUCCESS") diff --git a/testsuite/tests/dockerized/misc/default-cache/test.py b/testsuite/tests/dockerized/misc/default-cache/test.py index 1c5e0a74..cbb6b9eb 100644 --- a/testsuite/tests/dockerized/misc/default-cache/test.py +++ b/testsuite/tests/dockerized/misc/default-cache/test.py @@ -35,8 +35,11 @@ assert \ f"Vault not found at the expected location: f{contents(base)}" # Shared builds -# We hardcode this hash so we detect unwilling changes to our hashing scheme -hash = "7b5ad18029d4984b4076f4910c699700e7a325ab0c3dc786ccf89c3c6035212f" + +# We hardcode this hash so we detect unwilling changes to our hashing scheme. +# Every time this hash changes we must know the reason (changes in the hashing +# procedures) +hash = "1a29f0454348e767e78ac6912c7409b374b7bf650e81396c8a8750797ae073eb" assert \ os.path.isdir(f"{base}/builds/crate_real_1.0.0_filesystem_{hash}"), \ f"Shared build not found at the expected location: f{contents(base)}" -- 2.39.5