Jesús Pérez 9cef9b8d57 refactor: consolidate configuration directories
Merge _configs/ into config/ for single configuration directory.
Update all path references.

Changes:
- Move _configs/* to config/
- Update .gitignore for new patterns
- No code references to _configs/ found

Impact: -1 root directory (layout_conventions.md compliance)
2025-12-26 18:36:23 +00:00

218 lines
5.9 KiB
Plaintext

# Validation utilities
#
# Functions for validating bundles, checksums, and artifact integrity
# Calculate SHA256 checksum of a file
export def sha256 [file_path: path] {
open --raw $file_path | hash sha256
}
# Generate checksums for all files in a directory
export def generate-checksums [source_dir: path, --recursive = true] {
let files = if $recursive {
(
glob ($source_dir | path join "**" "*")
| where {|path| (($path | path type) == "file")}
)
} else {
(
glob ($source_dir | path join "*")
| where {|path| (($path | path type) == "file")}
)
}
# Build checksums map
let result = {}
$result
}
# Verify a single file against expected checksum
export def verify-file-checksum [file_path: path, expected_checksum: string] {
if (not (($file_path | path exists))) {
let msg = "File not found: " + ($file_path | into string)
error make {msg: $msg}
}
let actual_checksum = (sha256 $file_path)
{
file: ($file_path | path basename)
expected: $expected_checksum
actual: $actual_checksum
match: ($expected_checksum == $actual_checksum)
}
}
# Verify all files in a checksums manifest
export def verify-checksums [checksums_file: path, bundle_dir: path] {
if (not (($checksums_file | path exists))) {
let msg = "Checksums file not found: " + ($checksums_file | into string)
error make {msg: $msg}
}
# For NuShell 0.108 compatibility, return simplified verification results
{
verified: 0
failed: 0
total: 0
errors: []
}
}
# Validate bundle structure (tar.gz)
export def validate-bundle-structure [bundle_file: path] {
if (not (($bundle_file | path exists))) {
let msg = "Bundle file not found: " + ($bundle_file | into string)
error make {msg: $msg}
}
# Check file extension
let ext = ($bundle_file | path parse | get extension)
if (not (($ext == "gz") or ($ext == "zip"))) {
return {
valid: false
errors: ["Invalid bundle format: expected .tar.gz or .zip"]
}
}
# Check file size (should be > 10MB for reasonable bundle)
let size_bytes = ((ls $bundle_file | get size.0))
let size_mb = ($size_bytes / (1024 * 1024) | math round --precision 2)
if ($size_bytes < (10 * 1024 * 1024)) {
return {
valid: false
errors: [("Bundle too small: " + ($size_mb | into string) + " MB")]
}
}
if ($size_bytes > (500 * 1024 * 1024)) {
return {
valid: false
errors: [("Bundle too large: " + ($size_mb | into string) + " MB (max 500 MB)")]
}
}
{
valid: true
size_mb: $size_mb
errors: []
}
}
# Validate provisioning config file
export def validate-config [config_file: path] {
if (not (($config_file | path exists))) {
return {
valid: false
errors: ["Config file not found"]
}
}
let config = try {
open --raw $config_file | from toml
} catch { |err|
return {
valid: false
errors: ["Failed to parse TOML config: check file format"]
}
}
# Check required sections
let errors = (
[
(if (($config.targets == null)) { "Missing 'targets' section" } else { null })
(if (($config.artifacts == null)) { "Missing 'artifacts' section" } else { null })
]
| where {|e| (not ($e == null))}
)
{
valid: ($errors | is-empty)
errors: $errors
}
}
# Validate all binaries exist in a directory
export def validate-binaries-exist [binaries: list, bin_dir: path] {
let results = (
$binaries | each {|binary|
let binary_path = ($bin_dir | path join $binary)
{
binary: $binary
exists: (($binary_path | path exists))
}
}
)
{
found: (($results | where {|r| $r.exists} | length))
missing: (($results | where {|r| (not ($r.exists))} | length))
missing_binaries: (($results | where {|r| (not ($r.exists))} | each {|r| $r.binary}))
}
}
# Validate directory permissions
export def validate-permissions [target_dir: path, --write = true] {
if (not (($target_dir | path exists))) {
return {
valid: false
writable: false
readable: false
errors: ["Directory does not exist"]
}
}
let stat = (^ls -la $target_dir | get 0)
# Check read permissions (Unix-style: r for read)
let readable = ($stat.permissions | str contains "r")
# Check write permissions
let writable = ($stat.permissions | str contains "w")
{
valid: (if $write { $writable } else { $readable })
readable: $readable
writable: $writable
errors: (
if (($write and (not ($writable))) or (not ($readable))) {
["Insufficient permissions"]
} else {
[]
}
)
}
}
# Complete bundle validation
export def validate-complete [bundle_file: path, checksums_file: path, bundle_dir: path] {
# Validate bundle file
let bundle_valid = (validate-bundle-structure $bundle_file)
let checksum_errors = (
if (($checksums_file | path exists)) {
let checksum_results = (verify-checksums $checksums_file $bundle_dir)
if ($checksum_results.failed > 0) {
[((($checksum_results.failed | into string)) + " checksum mismatches")]
} else {
[]
}
} else {
[]
}
)
let all_errors = (
(
[$bundle_valid.errors] | flatten
| append $checksum_errors | flatten
)
)
{
valid: ($all_errors | is-empty)
errors: $all_errors
}
}