From b40e351c28d410108b1d9db8fd61e952a14aad59 Mon Sep 17 00:00:00 2001 From: antono2 Date: Fri, 9 Oct 2026 10:38:06 +0200 Subject: [PATCH 1/2] Verify the complete release dependency graph in CI --- .github/workflows/test.yml | 9 +++++ scripts/check_installed_deps.vsh | 69 ++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 scripts/check_installed_deps.vsh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index af5943d..9c6eaee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,6 +39,9 @@ jobs: - uses: prantlf/setup-v-action@92f20bea50d2c9931a28c96bb4997a3c7357baf0 # v4 with: version: 0.5.2 + - name: Verify the declared dependency graph + shell: bash + run: v run source/modules/antono2/vkmemalloc/scripts/check_installed_deps.vsh - name: Install Vulkan development library run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libvulkan-volk-dev mesa-vulkan-drivers vulkan-validationlayers - name: Check formatting @@ -93,6 +96,9 @@ jobs: - uses: prantlf/setup-v-action@92f20bea50d2c9931a28c96bb4997a3c7357baf0 # v4 with: version: 0.5.2 + - name: Verify the declared dependency graph + shell: bash + run: v run source/modules/antono2/vkmemalloc/scripts/check_installed_deps.vsh - name: Install Vulkan SDK and SwiftShader test artifacts shell: bash run: bash source/modules/antono2/vulkan/.github/scripts/setup-vulkan-ci.sh 1.4.309.0 v1.2 @@ -202,6 +208,9 @@ jobs: - uses: prantlf/setup-v-action@92f20bea50d2c9931a28c96bb4997a3c7357baf0 # v4 with: version: 0.5.2 + - name: Verify the declared dependency graph + shell: bash + run: v run source/modules/antono2/vkmemalloc/scripts/check_installed_deps.vsh - name: Install native compiler and Vulkan development library run: sudo apt-get update && sudo apt-get install -y clang libvulkan-dev libvulkan-volk-dev - name: Run CPU policy tests with AddressSanitizer and UndefinedBehaviorSanitizer diff --git a/scripts/check_installed_deps.vsh b/scripts/check_installed_deps.vsh new file mode 100644 index 0000000..1ef3e07 --- /dev/null +++ b/scripts/check_installed_deps.vsh @@ -0,0 +1,69 @@ +#!/usr/bin/env -S v run + +// Verify direct and transitive release pins against the installed Git checkouts. +// Companion tags require an explicit --tag-suffix module=suffix argument. +import os +import v.vmod + +fn check_module(root string, modules string, suffixes map[string]string, mut checked map[string]string) ! { + manifest := vmod.from_file(os.join_path(root, 'v.mod'))! + for dependency in manifest.dependencies { + name, declared_tag := dependency.rsplit_once('@') or { + return error('Dependency is not pinned in ${root}: ${dependency}') + } + tag := declared_tag + suffixes[name] + if previous := checked[name] { + if previous != tag { + return error('Conflicting dependency pins for ${name}: ${previous} and ${tag}') + } + continue + } + module_dir := os.join_path(modules, ...name.split('.')) + actual := os.execute('git -C ${os.quoted_path(module_dir)} rev-parse HEAD') + expected := os.execute('git -C ${os.quoted_path(module_dir)} rev-parse ${os.quoted_path('refs/tags/' + tag + '^{commit}')}') + if actual.exit_code != 0 || expected.exit_code != 0 { + return error('Cannot verify installed ${name}@${tag}: ${actual.output}${expected.output}') + } + if actual.output.trim_space() != expected.output.trim_space() { + return error('Installed ${name} does not match ${tag}: ${actual.output.trim_space()}') + } + checked[name] = tag + println('Verified ${name}@${tag}') + check_module(module_dir, modules, suffixes, mut checked)! + } +} + +fn check_dependencies() ! { + mut suffixes := map[string]string{} + mut index := 1 + for index < os.args.len { + if os.args[index] != '--tag-suffix' || index + 1 >= os.args.len { + return error('Usage: v run scripts/check_installed_deps.vsh [--tag-suffix module=suffix]') + } + name, suffix := os.args[index + 1].split_once('=') or { + return error('--tag-suffix requires module=suffix') + } + if name == '' || suffix == '' || name in suffixes { + return error('Invalid or repeated tag suffix: ${os.args[index + 1]}') + } + suffixes[name] = suffix + index += 2 + } + root := os.dir(os.dir(os.real_path(@FILE))) + configured := os.getenv('VMODULES') + modules := if configured != '' { configured } else { os.join_path(os.home_dir(), '.vmodules') } + mut checked := map[string]string{} + check_module(root, modules, suffixes, mut checked)! + for name, _ in suffixes { + if name !in checked { + return error('Tag suffix did not match a dependency: ${name}') + } + } +} + +fn main() { + check_dependencies() or { + eprintln(err) + exit(1) + } +} From 48737fdae11a45013a958970545e0ed95a838752 Mon Sep 17 00:00:00 2001 From: antono2 Date: Fri, 9 Oct 2026 10:39:33 +0200 Subject: [PATCH 2/2] Use the stable compiler formatter for the dependency check --- scripts/check_installed_deps.vsh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/check_installed_deps.vsh b/scripts/check_installed_deps.vsh index 1ef3e07..2f851eb 100644 --- a/scripts/check_installed_deps.vsh +++ b/scripts/check_installed_deps.vsh @@ -20,7 +20,8 @@ fn check_module(root string, modules string, suffixes map[string]string, mut che } module_dir := os.join_path(modules, ...name.split('.')) actual := os.execute('git -C ${os.quoted_path(module_dir)} rev-parse HEAD') - expected := os.execute('git -C ${os.quoted_path(module_dir)} rev-parse ${os.quoted_path('refs/tags/' + tag + '^{commit}')}') + expected := os.execute('git -C ${os.quoted_path(module_dir)} rev-parse ${os.quoted_path( + 'refs/tags/' + tag + '^{commit}')}') if actual.exit_code != 0 || expected.exit_code != 0 { return error('Cannot verify installed ${name}@${tag}: ${actual.output}${expected.output}') }