| ([^<]+)<\/td> | ([^<]+)<\/td><\/tr>/, arr)) {
+ test_name = arr[1]
+ failure_msg = arr[2]
+ printf " %s\n → %s\n", test_name, failure_msg
+ }
+ }
+ ' vi-analyzer-report.htm
+ echo ""
+ HAS_ERRORS=1
+fi
+
+if [ "$VI_NOT_LOADABLE" -gt 0 ]; then
+ echo "=================================================="
+ echo " VI Not Loadable Errors"
+ echo "=================================================="
+
+ awk '
+ /VI Not Loadable<\/h3>/,/<\/table>/ {
+ # Extract all table rows from the line
+ line = $0
+ while (match(line, /| ([^<]+)<\/td> | ([^<]+)<\/td> | ([^<]+)<\/td><\/tr>/, arr)) {
+ vi_name = arr[1]
+ vi_path = arr[2]
+ error_msg = arr[3]
+ printf "\n %s\n", vi_name
+ printf " Path: %s\n", vi_path
+ printf " → %s\n", error_msg
+ # Remove the matched portion and continue
+ line = substr(line, RSTART + RLENGTH)
+ }
+ }
+ ' vi-analyzer-report.htm
+ echo ""
+ HAS_ERRORS=1
+fi
+
+if [ "$TEST_NOT_LOADABLE" -gt 0 ]; then
+ echo "=================================================="
+ echo " Test Not Loadable Errors"
+ echo "=================================================="
+
+ awk '
+ /Test Not Loadable<\/h3>/ { in_section = 1; next }
+ in_section && // { exit }
+ in_section && / ([^<]+)<\/b>/ {
+ match($0, / ([^<]+)<\/b>/, arr)
+ if (current_test != "") print ""
+ current_test = arr[1]
+ printf "\n[%s]\n", current_test
+ next
+ }
+ in_section && // {
+ # Extract all table rows from this line and subsequent lines
+ line = $0
+ # Keep reading lines until we hit or next section
+ while (line !~ /<\/table>/ && getline nextline > 0) {
+ line = line nextline
+ if (line ~ /<\/table>/) break
+ }
+ # Now process all rows in the accumulated line
+ while (match(line, /| ([^<]+)<\/td> | ([^<]+)<\/td> | ([^<]+)<\/td><\/tr>/, arr)) {
+ vi_name = arr[1]
+ vi_path = arr[2]
+ error_msg = arr[3]
+ printf " %s\n", vi_name
+ printf " → %s\n", error_msg
+ line = substr(line, RSTART + RLENGTH)
+ }
+ }
+ ' vi-analyzer-report.htm
+ echo ""
+ HAS_ERRORS=1
+fi
+
+if [ "$TEST_NOT_RUNNABLE" -gt 0 ]; then
+ echo "=================================================="
+ echo " Test Not Runnable Errors"
+ echo "=================================================="
+
+ awk '
+ /Test Not Runnable<\/h3>/ { in_section = 1; next }
+ in_section && // { exit }
+ in_section && / ([^<]+)<\/b>/ {
+ match($0, / ([^<]+)<\/b>/, arr)
+ if (current_test != "") print ""
+ current_test = arr[1]
+ printf "\n[%s]\n", current_test
+ next
+ }
+ in_section && // {
+ # Extract all table rows from this line and subsequent lines
+ line = $0
+ # Keep reading lines until we hit or next section
+ while (line !~ /<\/table>/ && getline nextline > 0) {
+ line = line nextline
+ if (line ~ /<\/table>/) break
+ }
+ # Now process all rows in the accumulated line
+ while (match(line, /| ([^<]+)<\/td> | ([^<]+)<\/td> | ([^<]+)<\/td><\/tr>/, arr)) {
+ vi_name = arr[1]
+ vi_path = arr[2]
+ error_msg = arr[3]
+ printf " %s\n", vi_name
+ printf " → %s\n", error_msg
+ line = substr(line, RSTART + RLENGTH)
+ }
+ }
+ ' vi-analyzer-report.htm
+ echo ""
+ HAS_ERRORS=1
+fi
+
+if [ "$TEST_ERROR_OUT" -gt 0 ]; then
+ echo "=================================================="
+ echo " Test Error Out Errors"
+ echo "=================================================="
+
+ awk '
+ /Test Error Out<\/h3>/ { in_section = 1; next }
+ in_section && // { exit }
+ in_section && / ([^<]+)<\/b>/ {
+ match($0, / ([^<]+)<\/b>/, arr)
+ if (current_test != "") print ""
+ current_test = arr[1]
+ printf "\n[%s]\n", current_test
+ next
+ }
+ in_section && // {
+ # Extract all table rows from this line and subsequent lines
+ line = $0
+ # Keep reading lines until we hit or next section
+ while (line !~ /<\/table>/ && getline nextline > 0) {
+ line = line nextline
+ if (line ~ /<\/table>/) break
+ }
+ # Now process all rows in the accumulated line
+ while (match(line, /| ([^<]+)<\/td> | ([^<]+)<\/td> | ([^<]+)<\/td><\/tr>/, arr)) {
+ vi_name = arr[1]
+ vi_path = arr[2]
+ error_msg = arr[3]
+ printf " %s\n", vi_name
+ printf " → %s\n", error_msg
+ line = substr(line, RSTART + RLENGTH)
+ }
+ }
+ ' vi-analyzer-report.htm
+ echo ""
+ HAS_ERRORS=1
+fi
+
+if [ "$HAS_ERRORS" -eq 1 ]; then
+ echo ""
+ echo "=================================================="
+ echo "See full report in artifacts for complete details."
+ echo "=================================================="
+else
+ echo " All tests passed!"
+ echo "=================================================="
+fi
+
+exit $VIA_EXIT_CODE
\ No newline at end of file
diff --git a/scripts/via-lv-docker/run-via.sh b/scripts/via-lv-docker/run-via.sh
new file mode 100644
index 00000000..21c623de
--- /dev/null
+++ b/scripts/via-lv-docker/run-via.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+set -e
+
+# VI Analyzer script for GitHub Actions
+
+# Accept config path as first argument, default to generated-config.viancfg
+CONFIG_PATH="${1:-generated-config.viancfg}"
+ABSOLUTE_CONFIG="/workspace/$CONFIG_PATH"
+ABSOLUTE_REPORT="/workspace/vi-analyzer-report.htm"
+LV_YEAR="${LV_YEAR:-2025}"
+LABVIEW_PATH="/usr/local/natinst/LabVIEW-${LV_YEAR}-64/labview"
+
+# Verify that the configuration path exists
+if [ ! -d "$ABSOLUTE_CONFIG" ] && [ ! -f "$ABSOLUTE_CONFIG" ]; then
+ echo "Error: Configuration path not found at $ABSOLUTE_CONFIG"
+ exit 1
+fi
+
+echo "Running LabVIEWCLI VIAnalyzer with the following parameters:"
+echo "ConfigPath: $ABSOLUTE_CONFIG"
+echo "ReportPath: $ABSOLUTE_REPORT"
+echo "LabVIEWPath: $LABVIEW_PATH"
+echo ""
+
+# Run VI Analyzer
+LabVIEWCLI \
+ -OperationName RunVIAnalyzer \
+ -ConfigPath "$ABSOLUTE_CONFIG" \
+ -ReportPath "$ABSOLUTE_REPORT" \
+ -ReportSaveType HTML \
+ -LabVIEWPath "$LABVIEW_PATH" \
+ -Headless
\ No newline at end of file
diff --git a/scripts/via-lv-docker/via_template_linux.viancfg b/scripts/via-lv-docker/via_template_linux.viancfg
new file mode 100644
index 00000000..a59f9236
--- /dev/null
+++ b/scripts/via-lv-docker/via_template_linux.viancfg
@@ -0,0 +1,1057 @@
+
+
+1
+FALSE
+"/"
+0
+
+ -
+ "."
+ FALSE
+
+
+
+
+ "Arrays and Strings in Loops"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Arrays and Strings in Loops.llb"
+ TRUE
+
+
+
+
+ "Coercion Dots"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Coercion Dots.llb"
+ TRUE
+
+
+
+
+ "Enabled Debugging"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Enabled Debugging.llb"
+ TRUE
+
+
+
+
+ "In Place Element Structure Usage"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/In Place Element Structure Usage.llb"
+ TRUE
+
+
+
+
+ "Inlinable VIs"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Inlinable VIs.llb"
+ TRUE
+
+
+
+
+ "Parallel For Loop Debugging"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Parallel For Loop Debugging.llb"
+ TRUE
+
+
+
+
+ "Parallelizable Loops"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Parallelizable Loops.llb"
+ TRUE
+
+
+
+
+ "Prepend Scalar With Build Array"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Prepend Scalar With Build Array.llb"
+ TRUE
+
+
+
+
+ "Redundant Boolean Operations"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Redundant Boolean Operations.llb"
+ TRUE
+
+
+
+
+ "Value Property Usage"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Value Property Usage.llb"
+ TRUE
+
+
+
+
+ "Wait in While Loop"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Wait in While Loop.llb"
+ TRUE
+
+
+
+
+ "Wired Terminals in Subdiagrams"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Performance/Wired Terminals in Subdiagrams.llb"
+ TRUE
+
+
+
+
+ "Array Constant Style"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Array Constant Style.llb"
+ TRUE
+
+
+
+
+ "Backwards Wires"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Backwards Wires.llb"
+ TRUE
+
+
+
+
+ "Case Structure Default Frame"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Case Structure Default Frame.llb"
+ TRUE
+
+
+
+
+ "Code Simplification"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Code Simplification.llb"
+ TRUE
+
+
+
+
+ "Control Terminal Label Visible"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Control Terminal Label Visible.llb"
+ TRUE
+
+
+
+
+ "Control Terminal Wiring"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Control Terminal Wiring.llb"
+ TRUE
+
+
+
+
+ "Diagram Disable Structures"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Diagram Disable Structures.llb"
+ TRUE
+
+
+
+
+ "Mixed Terminal Styles"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Mixed Terminal Styles.llb"
+ TRUE
+
+
+
+
+ "Poor Names of Enum Items"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Poor Names of Enum Items.llb"
+ TRUE
+
+
+
+
+ "Sequence Structure Usage"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Sequence Structure Usage.llb"
+ TRUE
+
+
+
+
+ "String Constant Style"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/String Constant Style.llb"
+ TRUE
+
+
+
+
+ "Tunnel Position"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Tunnel Position.llb"
+ TRUE
+
+
+
+
+ "Unused Code"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Unused Code.llb"
+ TRUE
+
+
+
+
+ "Wire Bends"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Wire Bends.llb"
+ TRUE
+
+
+
+
+ "Wire Crossings"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Wire Crossings.llb"
+ TRUE
+
+
+
+
+ "Wires Under Objects"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Style/Wires Under Objects.llb"
+ TRUE
+
+
+
+
+ "Adding Array Size Elements"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Adding Array Size Elements.llb"
+ TRUE
+
+
+
+
+ "Array Sum and Product Overflow"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Array Sum and Product Overflow.llb"
+ TRUE
+
+
+
+
+ "Breakpoint Detection"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Breakpoint Detection.llb"
+ TRUE
+
+
+
+
+ "Bundling Duplicate Names"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Bundling Duplicate Names.llb"
+ TRUE
+
+
+
+
+ "Case Structure with String Range"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Case Structure with String Range.llb"
+ TRUE
+
+
+
+
+ "Error Cluster Wired"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Error Cluster Wired.llb"
+ TRUE
+
+
+
+
+ "Find Deprecated Items"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Find Deprecated Items.llb"
+ TRUE
+
+
+
+
+ "For Loop Error Handling"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/For Loop Error Handling.llb"
+ TRUE
+
+
+
+
+ "For Loop Iteration Count"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/For Loop Iteration Count.llb"
+ TRUE
+
+
+
+
+ "For Loop Reference Handling"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/For Loop Reference Handling.llb"
+ TRUE
+
+
+
+
+ "Globals and Locals"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Globals and Locals.llb"
+ TRUE
+
+
+
+
+ "Hidden Objects in Structures"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Hidden Objects in Structures.llb"
+ TRUE
+
+
+
+
+ "Hidden Tunnels"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Hidden Tunnels.llb"
+ TRUE
+
+
+
+
+ "Indexer Datatype"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Indexer Datatype.llb"
+ TRUE
+
+
+
+
+ "Pattern Label"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Pattern Label.llb"
+ TRUE
+
+
+
+
+ "Reentrant VI Issues"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Reentrant VI Issues.llb"
+ TRUE
+
+
+
+
+ "Type Casting References"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Type Casting References.llb"
+ TRUE
+
+
+
+
+ "Unwired I32 Error"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Block Diagram/Warnings/Unwired I32 Error.llb"
+ TRUE
+
+
+
+
+ "Cyclomatic Complexity"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Complexity Metrics/Cyclomatic Complexity.llb"
+ TRUE
+
+
+
+
+ "Depth of Nesting of Structures"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Complexity Metrics/Depth of Nesting of Structures.llb"
+ TRUE
+
+
+
+
+ "Fan In"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Complexity Metrics/Fan In.llb"
+ TRUE
+
+
+
+
+ "Fan Out"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Complexity Metrics/Fan Out.llb"
+ TRUE
+
+
+
+
+ "Modularity Index"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Complexity Metrics/Modularity Index.llb"
+ TRUE
+
+
+
+
+ "Approved Bookmark Tags"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Documentation/Developer/Approved Bookmark Tags.llb"
+ TRUE
+
+
+
+
+ "Comment Usage"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Documentation/Developer/Comment Usage.llb"
+ TRUE
+
+
+
+
+ "Label Call Library Nodes"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Documentation/Developer/Label Call Library Nodes.llb"
+ TRUE
+
+
+
+
+ "Revision History"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Documentation/Developer/Revision History.llb"
+ TRUE
+
+
+
+
+ "Spell Check"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Documentation/User/Spell Check.llb"
+ TRUE
+
+
+
+
+ "VI Documentation"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Documentation/User/VI Documentation.llb"
+ TRUE
+
+
+
+
+ "Array Default Values"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/SubVI/Array Default Values.llb"
+ TRUE
+
+
+
+
+ "Cluster Sized to Fit"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/SubVI/Cluster Sized to Fit.llb"
+ TRUE
+
+
+
+
+ "Control Alignment"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/SubVI/Control Alignment.llb"
+ TRUE
+
+
+
+
+ "Alignment Grid Setting"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Alignment Grid Setting.llb"
+ TRUE
+
+
+
+
+ "Clipped Text"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Clipped Text.llb"
+ TRUE
+
+
+
+
+ "Dialog Controls"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Dialog Controls.llb"
+ TRUE
+
+
+
+
+ "Duplicate Control Labels"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Duplicate Control Labels.llb"
+ TRUE
+
+
+
+
+ "Empty List Items"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Empty List Items.llb"
+ TRUE
+
+
+
+
+ "Font Usage"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Font Usage.llb"
+ TRUE
+
+
+
+
+ "Overlapping Controls"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Overlapping Controls.llb"
+ TRUE
+
+
+
+
+ "Panel Size and Position"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Panel Size and Position.llb"
+ TRUE
+
+
+
+
+ "Scalar Chart Updates"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Scalar Chart Updates.llb"
+ TRUE
+
+
+
+
+ "Synchronous Display"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Synchronous Display.llb"
+ TRUE
+
+
+
+
+ "Transparent Labels"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/Front Panel/User Interface/Transparent Labels.llb"
+ TRUE
+
+
+
+
+ "SubVI and TypeDef Locations"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/File Properties/SubVI and TypeDef Locations.llb"
+ TRUE
+
+
+
+
+ "VI Extension"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/File Properties/VI Extension.llb"
+ TRUE
+
+
+
+
+ "VI Name"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/File Properties/VI Name.llb"
+ TRUE
+
+
+
+
+ "VI Saved Version"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/File Properties/VI Saved Version.llb"
+ TRUE
+
+
+
+
+ "VI Size"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/File Properties/VI Size.llb"
+ TRUE
+
+
+
+
+ "Connector Pane Alignment"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Connector Pane Alignment.llb"
+ TRUE
+
+
+
+
+ "Connector Pane Pattern"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Connector Pane Pattern.llb"
+ TRUE
+
+
+
+
+ "Default Icon"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Default Icon.llb"
+ TRUE
+
+
+
+
+ "Error Style"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Error Style.llb"
+ TRUE
+
+
+
+
+ "Full Connector Pane"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Full Connector Pane.llb"
+ TRUE
+
+
+
+
+ "Icon Size and Border"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Icon Size and Border.llb"
+ TRUE
+
+
+
+
+ "Polymorphic Terminals"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Polymorphic Terminals.llb"
+ TRUE
+
+
+
+
+ "Terminal Connection Type"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Terminal Connection Type.llb"
+ TRUE
+
+
+
+
+ "Terminal Positions"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/Icon and Connector Pane/Terminal Positions.llb"
+ TRUE
+
+
+
+
+ "Auto Error Handling Enabled"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Auto Error Handling Enabled.llb"
+ TRUE
+
+
+
+
+ "Broken VI"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Broken VI.llb"
+ TRUE
+
+
+
+
+ "Built Application Compatibility"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Built Application Compatibility.llb"
+ TRUE
+
+
+
+
+ "Control VI Type"
+ 1
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Control VI Type.llb"
+ TRUE
+
+
+
+
+ "Driver Usage"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Driver Usage.llb"
+ TRUE
+
+
+
+
+ "Platform Portability"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Platform Portability.llb"
+ TRUE
+
+
+
+
+ "Removed Diagram"
+ 2
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Removed Diagram.llb"
+ TRUE
+
+
+
+
+ "Separate Compiled Code Setting"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Separate Compiled Code Setting.llb"
+ TRUE
+
+
+
+
+ "Toolkit Usage"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/Toolkit Usage.llb"
+ TRUE
+
+
+
+
+ "VI Lock State"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/General/VI Properties/VI Lock State.llb"
+ TRUE
+
+
+
+
+ "Connector Inputs and Outputs"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Connector Inputs and Outputs.llb"
+ TRUE
+
+
+
+
+ "Controls and Indicators"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Controls and Indicators.llb"
+ TRUE
+
+
+
+
+ "Diagram Count"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Diagram Count.llb"
+ TRUE
+
+
+
+
+ "Diagram Size"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Diagram Size.llb"
+ TRUE
+
+
+
+
+ "Node Count"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Node Count.llb"
+ TRUE
+
+
+
+
+ "Property Reads and Writes"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Property Reads and Writes.llb"
+ TRUE
+
+
+
+
+ "Shared Library Calls"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Shared Library Calls.llb"
+ TRUE
+
+
+
+
+ "Structure Count"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Structure Count.llb"
+ TRUE
+
+
+
+
+ "Wire Sources"
+ 0
+ 5
+ "LabVIEW"
+ "project/_VI Analyzer/_tests/VI Metrics/Wire Sources.llb"
+ TRUE
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/pester/ViaLvDocker.Workflow.Tests.ps1 b/tests/pester/ViaLvDocker.Workflow.Tests.ps1
new file mode 100644
index 00000000..db82d507
--- /dev/null
+++ b/tests/pester/ViaLvDocker.Workflow.Tests.ps1
@@ -0,0 +1,37 @@
+#requires -Version 7.0
+Set-StrictMode -Version Latest
+$ErrorActionPreference = 'Stop'
+
+Describe 'ViaLvDocker.Workflow' {
+ $meta = @{
+ requirement = 'REQ-034'
+ Owner = 'DevTools'
+ Evidence = 'tests/pester/ViaLvDocker.Workflow.Tests.ps1'
+ }
+
+ It 'runs via-lv-docker action on ubuntu-latest runner [REQ-034]' -Tag 'REQ-034' {
+ $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..' '..')).Path
+ $actionPath = Join-Path $repoRoot 'via-lv-docker/action.yml'
+
+ # Verify action.yml exists
+ $actionPath | Should -Exist
+
+ # Parse action.yml
+ $actionContent = Get-Content -Raw $actionPath
+ $actionContent | Should -Not -BeNullOrEmpty
+
+ # Verify key inputs are defined
+ $actionContent | Should -Match 'config_path:'
+ $actionContent | Should -Match 'template_path:'
+ $actionContent | Should -Match 'base_branch:'
+ $actionContent | Should -Match 'labview_version:'
+ $actionContent | Should -Match 'docker_image:'
+
+ # Verify it uses composite action pattern
+ $actionContent | Should -Match "using: 'composite'"
+
+ # Verify it calls the dispatcher
+ $actionContent | Should -Match 'common-dispatch.ps1'
+ $actionContent | Should -Match "ActionName = 'via-lv-docker'"
+ }
+}
\ No newline at end of file
diff --git a/via-lv-docker/action.yml b/via-lv-docker/action.yml
new file mode 100644
index 00000000..a4785692
--- /dev/null
+++ b/via-lv-docker/action.yml
@@ -0,0 +1,60 @@
+name: 'Run VI Analyzer with LabVIEW Container'
+description: 'Execute LabVIEW VI Analyzer tests using Docker container and parse results'
+
+inputs:
+ config_path:
+ description: 'Path to VI Analyzer configuration file (.viancfg) or LabVIEW files (.vi, .ctl, .llb)'
+ required: false
+ default: ''
+ template_path:
+ description: 'Path to .viancfg template (required to generate config file dynamically)'
+ required: false
+ default: ''
+ base_branch:
+ description: 'Branch to compare against for changed files (used when generating config)'
+ required: false
+ default: 'origin/develop'
+ labview_version:
+ description: 'LabVIEW Docker image version tag'
+ required: false
+ default: '2026q1-linux'
+ docker_image:
+ description: 'Full Docker image name'
+ required: false
+ default: 'nationalinstruments/labview'
+ working_directory:
+ description: 'Working directory where the action will run.'
+ required: false
+ log_level:
+ description: 'Verbosity level (ERROR|WARN|INFO|DEBUG).'
+ default: 'INFO'
+ required: false
+ dry_run:
+ description: 'If true, simulate the action without side effects.'
+ default: false
+ required: false
+
+runs:
+ using: 'composite'
+ steps:
+ - name: Dispatch via-lv-docker
+ shell: pwsh
+ run: |
+ $ErrorActionPreference = 'Stop'
+ $args = @{
+ ConfigPath = '${{ inputs.config_path }}'
+ TemplatePath = '${{ inputs.template_path }}'
+ BaseBranch = '${{ inputs.base_branch }}'
+ LabviewVersion = '${{ inputs.labview_version }}'
+ DockerImage = '${{ inputs.docker_image }}'
+ }
+ $params = @{
+ ActionName = 'via-lv-docker'
+ Args = $args
+ LogLevel = '${{ inputs.log_level }}'
+ }
+ if ('${{ inputs.dry_run }}' -eq 'true') { $params['DryRun'] = $true }
+ if ('${{ inputs.working_directory }}') { $params['WorkingDirectory'] = '${{ inputs.working_directory }}' }
+ $script = Join-Path $env:GITHUB_ACTION_PATH '..' 'actions' 'common-dispatch.ps1'
+ & $script @params
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
\ No newline at end of file
| | | | |