From e1d755af000697f7d36cea88578236127f6be19a Mon Sep 17 00:00:00 2001 From: Amrutha G Date: Tue, 8 Sep 2026 14:17:10 +0530 Subject: [PATCH 1/3] Add VIPM TOML and lockfile dependency support --- .github/workflows/vipm-lock-refresh.yml | 25 +++ actions/OpenSourceActions.psm1 | 24 +++ apply-vipc/action.yml | 8 + build-spec-docker-linux/action.yml | 10 ++ build-spec-docker-windows/action.yml | 10 ++ build-spec-github-hosted-windows/action.yml | 10 ++ dispatchers.json | 54 ++++++- scripts/apply-vipc/ApplyVIPC.ps1 | 41 ++++- scripts/apply-vipc/vipm.toml | 22 +++ .../BuildSpecDockerLinux.ps1 | 19 ++- scripts/build-spec-docker-linux/build-spec.sh | 27 ++++ .../BuildSpecDockerWindows.ps1 | 17 ++- .../build-spec-docker-windows/build-spec.ps1 | 20 ++- .../BuildSpecGithubHostedWindows.ps1 | 20 ++- scripts/vipm-common/Invoke-VipmInstall.ps1 | 143 ++++++++++++++++++ scripts/vipm-common/New-VipmLock.ps1 | 115 ++++++++++++++ scripts/vipm-common/install-vipm-deps.sh | 86 +++++++++++ 17 files changed, 642 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/vipm-lock-refresh.yml create mode 100644 scripts/apply-vipc/vipm.toml create mode 100644 scripts/vipm-common/Invoke-VipmInstall.ps1 create mode 100644 scripts/vipm-common/New-VipmLock.ps1 create mode 100644 scripts/vipm-common/install-vipm-deps.sh diff --git a/.github/workflows/vipm-lock-refresh.yml b/.github/workflows/vipm-lock-refresh.yml new file mode 100644 index 00000000..4771a5bd --- /dev/null +++ b/.github/workflows/vipm-lock-refresh.yml @@ -0,0 +1,25 @@ +name: Refresh VIPM Lock + +on: + workflow_dispatch: + +jobs: + refresh-vipm-lock: + runs-on: windows-latest + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 + - name: Generate or refresh vipm.lock + shell: pwsh + env: + VIPM_SERIAL_NUMBER: ${{ secrets.VIPM_SERIAL_NUMBER }} + VIPM_FULL_NAME: ${{ secrets.VIPM_FULL_NAME }} + VIPM_EMAIL: ${{ secrets.VIPM_EMAIL }} + run: | + $ErrorActionPreference = 'Stop' + scripts/vipm-common/New-VipmLock.ps1 -VipmToml 'scripts/apply-vipc/vipm.toml' + - name: Upload vipm.lock artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: vipm-lock + path: 'scripts/apply-vipc/vipm.lock' + if-no-files-found: error diff --git a/actions/OpenSourceActions.psm1 b/actions/OpenSourceActions.psm1 index fd12abd9..06ab59f4 100644 --- a/actions/OpenSourceActions.psm1 +++ b/actions/OpenSourceActions.psm1 @@ -66,6 +66,8 @@ function Invoke-AddTokenToLabVIEW { # SupportedBitness: Target LabVIEW bitness (32- or 64-bit). # RelativePath: Normalized path to the project root relative to the working directory. # VIPCPath: Optional path to the VIPC file. +# VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. +# VipmLock: Optional path to a VIPM lock file verified against the manifest before install. # DryRun: If set, prints the command instead of executing it. # gcliPath: Optional path prepended to PATH for locating the g CLI. function Invoke-ApplyVIPC { @@ -76,6 +78,8 @@ function Invoke-ApplyVIPC { [Parameter(Mandatory)] [string] $SupportedBitness, [Parameter(Mandatory)] [string] $RelativePath, [Parameter()] [string] $VIPCPath, + [Parameter()] [string] $VipmToml, + [Parameter()] [string] $VipmLock, [Parameter()] [switch] $DryRun, [Parameter()] [string] $gcliPath ) @@ -86,6 +90,8 @@ function Invoke-ApplyVIPC { SupportedBitness = $SupportedBitness RelativePath = $RelativePath VIPCPath = $VIPCPath + VipmToml = $VipmToml + VipmLock = $VipmLock } return Invoke-OpenSourceActionScript -ScriptSegments @('apply-vipc','ApplyVIPC.ps1') -Arguments $args -DryRun:$DryRun -gcliPath $gcliPath } @@ -241,6 +247,8 @@ function Invoke-BuildLvlibp { # Commit: Commit hash or identifier (optional). # DockerImage: Docker image name (default: "nationalinstruments/labview"). # ImageTag: Docker image tag (defaults to "2026q1-linux"). +# VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. +# VipmLock: Optional path to a VIPM lock file verified against the manifest before install. # DryRun: If set, prints the command instead of executing it. # gcliPath: Optional path prepended to PATH for locating the g CLI. function Invoke-BuildSpecDockerLinux { @@ -258,6 +266,8 @@ function Invoke-BuildSpecDockerLinux { [Parameter()] [string] $Commit = "", [Parameter()] [string] $DockerImage = "nationalinstruments/labview", [Parameter()] [string] $ImageTag = "2026q1-linux", + [Parameter()] [string] $VipmToml = "", + [Parameter()] [string] $VipmLock = "", [switch] $DryRun, [string] $gcliPath ) @@ -278,6 +288,8 @@ function Invoke-BuildSpecDockerLinux { Commit = $Commit DockerImage = $DockerImage ImageTag = $ImageTag + VipmToml = $VipmToml + VipmLock = $VipmLock } ` -DryRun:$DryRun ` -gcliPath $gcliPath @@ -298,6 +310,8 @@ function Invoke-BuildSpecDockerLinux { # Commit: Commit hash or identifier (optional). # DockerImage: Docker image name (default: "nationalinstruments/labview"). # ImageTag: Docker image tag (defaults to "2026q1-windows"). +# VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. +# VipmLock: Optional path to a VIPM lock file verified against the manifest before install. # DryRun: If set, prints the command instead of executing it. # gcliPath: Optional path prepended to PATH for locating the g CLI. function Invoke-BuildSpecDockerWindows { @@ -315,6 +329,8 @@ function Invoke-BuildSpecDockerWindows { [Parameter()] [string] $Commit = "", [Parameter()] [string] $DockerImage = "nationalinstruments/labview", [Parameter()] [string] $ImageTag = "2026q1-windows", + [Parameter()] [string] $VipmToml = "", + [Parameter()] [string] $VipmLock = "", [switch] $DryRun, [string] $gcliPath ) @@ -335,6 +351,8 @@ function Invoke-BuildSpecDockerWindows { Commit = $Commit DockerImage = $DockerImage ImageTag = $ImageTag + VipmToml = $VipmToml + VipmLock = $VipmLock } ` -DryRun:$DryRun ` -gcliPath $gcliPath @@ -353,6 +371,8 @@ function Invoke-BuildSpecDockerWindows { # Patch: Patch version component (optional, skips version setting if < 0). # Build: Build number component (optional, skips version setting if < 0). # Commit: Commit hash or identifier (optional). +# VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. +# VipmLock: Optional path to a VIPM lock file verified against the manifest before install. # DryRun: If set, prints the command instead of executing it. # gcliPath: Optional path prepended to PATH for locating the g CLI. function Invoke-BuildSpecGithubHostedWindows { @@ -368,6 +388,8 @@ function Invoke-BuildSpecGithubHostedWindows { [Parameter()] [int] $Patch = -1, [Parameter()] [int] $Build = -1, [Parameter()] [string] $Commit = "", + [Parameter()] [string] $VipmToml = "", + [Parameter()] [string] $VipmLock = "", [switch] $DryRun, [string] $gcliPath ) @@ -386,6 +408,8 @@ function Invoke-BuildSpecGithubHostedWindows { Patch = $Patch Build = $Build Commit = $Commit + VipmToml = $VipmToml + VipmLock = $VipmLock } ` -DryRun:$DryRun ` -gcliPath $gcliPath diff --git a/apply-vipc/action.yml b/apply-vipc/action.yml index e12a11d4..2825a15c 100644 --- a/apply-vipc/action.yml +++ b/apply-vipc/action.yml @@ -16,6 +16,12 @@ inputs: vipc_path: description: 'Path to the VIPC file.' required: false + vipm_toml: + description: 'Path to a vipm.toml manifest. When set, dependencies are installed via the VIPM CLI instead of a .vipc.' + required: false + vipm_lock: + description: 'Path to a vipm.lock file to verify against the manifest before install.' + required: false gcli_path: description: 'Optional path to the g-cli executable.' required: false @@ -44,6 +50,8 @@ runs: RelativePath = '${{ inputs.relative_path }}' } if ('${{ inputs.vipc_path }}') { $args['VIPCPath'] = '${{ inputs.vipc_path }}' } + if ('${{ inputs.vipm_toml }}') { $args['VipmToml'] = '${{ inputs.vipm_toml }}' } + if ('${{ inputs.vipm_lock }}') { $args['VipmLock'] = '${{ inputs.vipm_lock }}' } if ('${{ inputs.gcli_path }}') { $args['gcliPath'] = '${{ inputs.gcli_path }}' } $params = @{ ActionName = 'apply-vipc' diff --git a/build-spec-docker-linux/action.yml b/build-spec-docker-linux/action.yml index d6e91624..73ed1e54 100644 --- a/build-spec-docker-linux/action.yml +++ b/build-spec-docker-linux/action.yml @@ -42,6 +42,14 @@ inputs: description: 'Docker image tag.' required: false default: '2026q1-linux' + vipm_toml: + description: 'Path to a vipm.toml manifest. When set, dependencies are installed via the VIPM CLI.' + required: false + default: '' + vipm_lock: + description: 'Path to a vipm.lock file to verify against the manifest before install.' + required: false + default: '' working_directory: description: 'Working directory where the action will run.' required: false @@ -77,6 +85,8 @@ runs: if ('${{ inputs.minor }}') { $args['Minor'] = [int]'${{ inputs.minor }}' } if ('${{ inputs.patch }}') { $args['Patch'] = [int]'${{ inputs.patch }}' } if ('${{ inputs.build }}') { $args['Build'] = [int]'${{ inputs.build }}' } + if ('${{ inputs.vipm_toml }}') { $args['VipmToml'] = '${{ inputs.vipm_toml }}' } + if ('${{ inputs.vipm_lock }}') { $args['VipmLock'] = '${{ inputs.vipm_lock }}' } $params = @{ ActionName = 'build-spec-docker-linux' diff --git a/build-spec-docker-windows/action.yml b/build-spec-docker-windows/action.yml index 2005f449..e585e72f 100644 --- a/build-spec-docker-windows/action.yml +++ b/build-spec-docker-windows/action.yml @@ -42,6 +42,14 @@ inputs: description: 'Docker image tag.' required: false default: '2026q1-windows' + vipm_toml: + description: 'Path to a vipm.toml manifest. When set, dependencies are installed via the VIPM CLI.' + required: false + default: '' + vipm_lock: + description: 'Path to a vipm.lock file to verify against the manifest before install.' + required: false + default: '' working_directory: description: 'Working directory where the action will run.' required: false @@ -77,6 +85,8 @@ runs: if ('${{ inputs.minor }}') { $args['Minor'] = [int]'${{ inputs.minor }}' } if ('${{ inputs.patch }}') { $args['Patch'] = [int]'${{ inputs.patch }}' } if ('${{ inputs.build }}') { $args['Build'] = [int]'${{ inputs.build }}' } + if ('${{ inputs.vipm_toml }}') { $args['VipmToml'] = '${{ inputs.vipm_toml }}' } + if ('${{ inputs.vipm_lock }}') { $args['VipmLock'] = '${{ inputs.vipm_lock }}' } $params = @{ ActionName = 'build-spec-docker-windows' diff --git a/build-spec-github-hosted-windows/action.yml b/build-spec-github-hosted-windows/action.yml index 0996c238..507e81d3 100644 --- a/build-spec-github-hosted-windows/action.yml +++ b/build-spec-github-hosted-windows/action.yml @@ -34,6 +34,14 @@ inputs: description: 'Commit hash or identifier recorded in the build.' required: false default: '' + vipm_toml: + description: 'Path to a vipm.toml manifest. When set, dependencies are installed via the VIPM CLI.' + required: false + default: '' + vipm_lock: + description: 'Path to a vipm.lock file to verify against the manifest before install.' + required: false + default: '' working_directory: description: 'Working directory where the action will run.' required: false @@ -67,6 +75,8 @@ runs: if ('${{ inputs.minor }}') { $args['Minor'] = [int]'${{ inputs.minor }}' } if ('${{ inputs.patch }}') { $args['Patch'] = [int]'${{ inputs.patch }}' } if ('${{ inputs.build }}') { $args['Build'] = [int]'${{ inputs.build }}' } + if ('${{ inputs.vipm_toml }}') { $args['VipmToml'] = '${{ inputs.vipm_toml }}' } + if ('${{ inputs.vipm_lock }}') { $args['VipmLock'] = '${{ inputs.vipm_lock }}' } $params = @{ ActionName = 'build-spec-github-hosted-windows' diff --git a/dispatchers.json b/dispatchers.json index 126b4f7a..f1b97900 100644 --- a/dispatchers.json +++ b/dispatchers.json @@ -30,7 +30,7 @@ } }, "Invoke-ApplyVIPC": { - "description": "Applies a VI Package Configuration to a LabVIEW project. MinimumSupportedLVVersion: Minimum LabVIEW version that the project supports. VIP_LVVersion: LabVIEW version used to build the VIPC. SupportedBitness: Target LabVIEW bitness (32- or 64-bit). RelativePath: Normalized path to the project root relative to the working directory. VIPCPath: Optional path to the VIPC file. DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", + "description": "Applies a VI Package Configuration to a LabVIEW project. MinimumSupportedLVVersion: Minimum LabVIEW version that the project supports. VIP_LVVersion: LabVIEW version used to build the VIPC. SupportedBitness: Target LabVIEW bitness (32- or 64-bit). RelativePath: Normalized path to the project root relative to the working directory. VIPCPath: Optional path to the VIPC file. VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. VipmLock: Optional path to a VIPM lock file verified against the manifest before install. DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", "parameters": { "DryRun": { "type": "boolean", @@ -66,6 +66,16 @@ "type": "string", "required": false, "description": "Optional path to the VIPC file" + }, + "VipmLock": { + "type": "string", + "required": false, + "description": "Optional path to a VIPM lock file verified against the manifest before install" + }, + "VipmToml": { + "type": "string", + "required": false, + "description": "Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI" } } }, @@ -195,7 +205,7 @@ } }, "Invoke-BuildSpecDockerLinux": { - "description": "Builds LabVIEW build specification using Linux Docker container. MinimumSupportedLVVersion: LabVIEW version for the build (e.g., \"2021\", \"2026\"). SupportedBitness: Bitness of the LabVIEW environment (\"32\" or \"64\"). ProjectPath: Path to the LabVIEW project .lvproj file. TargetName: Target that contains the build specification (optional, defaults to \"My Computer\"). BuildSpecName: Name of the LabVIEW build specification (optional, builds all if empty). Major: Major version component (optional, skips version setting if < 0). Minor: Minor version component (optional, skips version setting if < 0). Patch: Patch version component (optional, skips version setting if < 0). Build: Build number component (optional, skips version setting if < 0). Commit: Commit hash or identifier (optional). DockerImage: Docker image name (default: \"nationalinstruments/labview\"). ImageTag: Docker image tag (defaults to \"2026q1-linux\"). DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", + "description": "Builds LabVIEW build specification using Linux Docker container. MinimumSupportedLVVersion: LabVIEW version for the build (e.g., \"2021\", \"2026\"). SupportedBitness: Bitness of the LabVIEW environment (\"32\" or \"64\"). ProjectPath: Path to the LabVIEW project .lvproj file. TargetName: Target that contains the build specification (optional, defaults to \"My Computer\"). BuildSpecName: Name of the LabVIEW build specification (optional, builds all if empty). Major: Major version component (optional, skips version setting if < 0). Minor: Minor version component (optional, skips version setting if < 0). Patch: Patch version component (optional, skips version setting if < 0). Build: Build number component (optional, skips version setting if < 0). Commit: Commit hash or identifier (optional). DockerImage: Docker image name (default: \"nationalinstruments/labview\"). ImageTag: Docker image tag (defaults to \"2026q1-linux\"). VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. VipmLock: Optional path to a VIPM lock file verified against the manifest before install. DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", "parameters": { "Build": { "type": "number", @@ -275,11 +285,23 @@ "required": false, "default": "", "description": "Target that contains the build specification (optional, defaults to \"My Computer\")" + }, + "VipmLock": { + "type": "string", + "required": false, + "default": "", + "description": "Optional path to a VIPM lock file verified against the manifest before install" + }, + "VipmToml": { + "type": "string", + "required": false, + "default": "", + "description": "Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI" } } }, "Invoke-BuildSpecDockerWindows": { - "description": "Builds LabVIEW build specification using Windows Docker container. MinimumSupportedLVVersion: LabVIEW version for the build (e.g., \"2021\", \"2026\"). SupportedBitness: Bitness of the LabVIEW environment (\"32\" or \"64\"). ProjectPath: Path to the LabVIEW project .lvproj file. TargetName: Target that contains the build specification (optional, defaults to \"My Computer\"). BuildSpecName: Name of the LabVIEW build specification (optional, builds all if empty). Major: Major version component (optional, skips version setting if < 0). Minor: Minor version component (optional, skips version setting if < 0). Patch: Patch version component (optional, skips version setting if < 0). Build: Build number component (optional, skips version setting if < 0). Commit: Commit hash or identifier (optional). DockerImage: Docker image name (default: \"nationalinstruments/labview\"). ImageTag: Docker image tag (defaults to \"2026q1-windows\"). DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", + "description": "Builds LabVIEW build specification using Windows Docker container. MinimumSupportedLVVersion: LabVIEW version for the build (e.g., \"2021\", \"2026\"). SupportedBitness: Bitness of the LabVIEW environment (\"32\" or \"64\"). ProjectPath: Path to the LabVIEW project .lvproj file. TargetName: Target that contains the build specification (optional, defaults to \"My Computer\"). BuildSpecName: Name of the LabVIEW build specification (optional, builds all if empty). Major: Major version component (optional, skips version setting if < 0). Minor: Minor version component (optional, skips version setting if < 0). Patch: Patch version component (optional, skips version setting if < 0). Build: Build number component (optional, skips version setting if < 0). Commit: Commit hash or identifier (optional). DockerImage: Docker image name (default: \"nationalinstruments/labview\"). ImageTag: Docker image tag (defaults to \"2026q1-windows\"). VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. VipmLock: Optional path to a VIPM lock file verified against the manifest before install. DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", "parameters": { "Build": { "type": "number", @@ -359,11 +381,23 @@ "required": false, "default": "", "description": "Target that contains the build specification (optional, defaults to \"My Computer\")" + }, + "VipmLock": { + "type": "string", + "required": false, + "default": "", + "description": "Optional path to a VIPM lock file verified against the manifest before install" + }, + "VipmToml": { + "type": "string", + "required": false, + "default": "", + "description": "Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI" } } }, "Invoke-BuildSpecGithubHostedWindows": { - "description": "Builds LabVIEW build specification using Windows GitHub-hosted runner. MinimumSupportedLVVersion: LabVIEW version for the build (e.g., \"2021\", \"2026\"). SupportedBitness: Bitness of the LabVIEW environment (\"32\" or \"64\"). ProjectPath: Path to the LabVIEW project .lvproj file. TargetName: Target that contains the build specification (optional, defaults to \"My Computer\"). BuildSpecName: Name of the LabVIEW build specification (optional, builds all if empty). Major: Major version component (optional, skips version setting if < 0). Minor: Minor version component (optional, skips version setting if < 0). Patch: Patch version component (optional, skips version setting if < 0). Build: Build number component (optional, skips version setting if < 0). Commit: Commit hash or identifier (optional). DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", + "description": "Builds LabVIEW build specification using Windows GitHub-hosted runner. MinimumSupportedLVVersion: LabVIEW version for the build (e.g., \"2021\", \"2026\"). SupportedBitness: Bitness of the LabVIEW environment (\"32\" or \"64\"). ProjectPath: Path to the LabVIEW project .lvproj file. TargetName: Target that contains the build specification (optional, defaults to \"My Computer\"). BuildSpecName: Name of the LabVIEW build specification (optional, builds all if empty). Major: Major version component (optional, skips version setting if < 0). Minor: Minor version component (optional, skips version setting if < 0). Patch: Patch version component (optional, skips version setting if < 0). Build: Build number component (optional, skips version setting if < 0). Commit: Commit hash or identifier (optional). VipmToml: Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI. VipmLock: Optional path to a VIPM lock file verified against the manifest before install. DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", "parameters": { "Build": { "type": "number", @@ -431,6 +465,18 @@ "required": false, "default": "", "description": "Target that contains the build specification (optional, defaults to \"My Computer\")" + }, + "VipmLock": { + "type": "string", + "required": false, + "default": "", + "description": "Optional path to a VIPM lock file verified against the manifest before install" + }, + "VipmToml": { + "type": "string", + "required": false, + "default": "", + "description": "Optional path to a VIPM TOML manifest used to install dependencies via the VIPM CLI" } } }, diff --git a/scripts/apply-vipc/ApplyVIPC.ps1 b/scripts/apply-vipc/ApplyVIPC.ps1 index 8272121c..bf661d21 100644 --- a/scripts/apply-vipc/ApplyVIPC.ps1 +++ b/scripts/apply-vipc/ApplyVIPC.ps1 @@ -13,9 +13,48 @@ Param ( [string]$VIP_LVVersion, [string]$SupportedBitness, [string]$RelativePath, - [string]$VIPCPath + [string]$VIPCPath, + [string]$VipmToml, + [string]$VipmLock ) +# Auto-detect a vipm.toml alongside this script when one isn't provided explicitly. +if (-not $VipmToml) { + $defaultToml = Join-Path $PSScriptRoot 'vipm.toml' + if (Test-Path $defaultToml) { + $VipmToml = $defaultToml + Write-Verbose "Auto-detected VipmToml: $VipmToml" + } +} + +# Prefer vipm.toml/vipm.lock when provided; delegates to the shared VIPM helper. +if ($VipmToml) { + $ResolvedRelativePath = Resolve-Path -Path $RelativePath -ErrorAction Stop + if ([System.IO.Path]::IsPathRooted($VipmToml)) { + $tomlPath = $VipmToml + } else { + $tomlPath = Join-Path -Path $ResolvedRelativePath -ChildPath $VipmToml + } + $helperParams = @{ VipmToml = $tomlPath } + if ($VipmLock) { + if ([System.IO.Path]::IsPathRooted($VipmLock)) { + $helperParams['VipmLock'] = $VipmLock + } else { + $helperParams['VipmLock'] = Join-Path -Path $ResolvedRelativePath -ChildPath $VipmLock + } + } else { + $defaultLock = Join-Path (Split-Path -Parent $tomlPath) 'vipm.lock' + if (Test-Path $defaultLock) { $helperParams['VipmLock'] = $defaultLock } + } + $vipmHelper = Join-Path $PSScriptRoot '..' 'vipm-common' 'Invoke-VipmInstall.ps1' + if (-not (Test-Path $vipmHelper)) { + Write-Error "VIPM helper not found at: $vipmHelper" + exit 1 + } + & $vipmHelper @helperParams + exit $LASTEXITCODE +} + # Auto-detect the VIPC file if one isn't provided if (-not $VIPCPath) { $vipcFiles = Get-ChildItem -Path $PSScriptRoot -Filter *.vipc diff --git a/scripts/apply-vipc/vipm.toml b/scripts/apply-vipc/vipm.toml new file mode 100644 index 00000000..bcb18339 --- /dev/null +++ b/scripts/apply-vipc/vipm.toml @@ -0,0 +1,22 @@ +[project] +name = "runner-dependencies" +labview-version = 2021 +labview-bitness = 64 + +[dependencies] +wiresmith_technology_lib_g_cli = "3.0.1.98" +hse_lib_git_api = "2.3.4.176" +jki_lib_serialization = "1.0.1.14" +jki_lib_state_machine = "2024.0.3.23" +jki_lib_unicode = "1.0.0.7" +jki_rsc_toolkits_palette = "1.1-1" +astemes_lib_lunit = "1.10.7.3" +sas_workshops_lib_lunit_for_g_cli = "1.1.1.54" +oglib_array = "6.0.1.20" +oglib_error = "6.0.0.26" +oglib_file = "6.0.2.28" +oglib_lvzip = "5.0.9-1" +oglib_lvdata = "6.0.0.45" +jki_lib_vipm_api = "2020.0.3.80" +sas_workshops_lib_vipb_builder_for_g_cli = "1.1.6.46" +sas_workshops_lib_lvbuildspec_for_g_cli = "1.2.1.104" diff --git a/scripts/build-spec-docker-linux/BuildSpecDockerLinux.ps1 b/scripts/build-spec-docker-linux/BuildSpecDockerLinux.ps1 index bc010ea6..151f174a 100644 --- a/scripts/build-spec-docker-linux/BuildSpecDockerLinux.ps1 +++ b/scripts/build-spec-docker-linux/BuildSpecDockerLinux.ps1 @@ -84,7 +84,13 @@ param( [string]$DockerImage = "nationalinstruments/labview", [Parameter(Mandatory = $false)] - [string]$ImageTag = "2026q1-linux" + [string]$ImageTag = "2026q1-linux", + + [Parameter(Mandatory = $false)] + [string]$VipmToml = "", + + [Parameter(Mandatory = $false)] + [string]$VipmLock = "" ) Set-StrictMode -Version Latest @@ -162,6 +168,17 @@ try { $bashArgs += "--version", "'$versionString'" } + # Workspace is mounted at /workspace, so manifest paths are repo-relative. + if (-not [string]::IsNullOrWhiteSpace($VipmToml)) { + $bashArgs += "--vipm-toml", "'/workspace/$VipmToml'" + } + + # Optional: install-vipm-deps.sh auto-detects vipm.lock next to vipm.toml + # and fails if it's missing when not passed explicitly here. + if (-not [string]::IsNullOrWhiteSpace($VipmLock)) { + $bashArgs += "--vipm-lock", "'/workspace/$VipmLock'" + } + $bashCommand = "chmod +x $containerScriptPath && $containerScriptPath $($bashArgs -join ' ')" Write-Information "Executing build script in Docker container..." -InformationAction Continue diff --git a/scripts/build-spec-docker-linux/build-spec.sh b/scripts/build-spec-docker-linux/build-spec.sh index 0bddb8f3..03a00cfd 100644 --- a/scripts/build-spec-docker-linux/build-spec.sh +++ b/scripts/build-spec-docker-linux/build-spec.sh @@ -10,6 +10,8 @@ PROJECT_PATH="" TARGET_NAME="" BUILD_SPEC_NAME="" VERSION="" +VIPM_TOML="" +VIPM_LOCK="" while [[ $# -gt 0 ]]; do case $1 in @@ -33,6 +35,14 @@ while [[ $# -gt 0 ]]; do VERSION="$2" shift 2 ;; + --vipm-toml) + VIPM_TOML="$2" + shift 2 + ;; + --vipm-lock) + VIPM_LOCK="$2" + shift 2 + ;; *) echo "Unknown argument: $1" exit 1 @@ -94,6 +104,23 @@ else echo "Skipping version set" fi +# Install project dependencies from vipm.toml/vipm.lock before building. +# VIPM_LOCK is optional here: install-vipm-deps.sh auto-detects vipm.lock next +# to vipm.toml and fails if it's missing, matching the Windows build path. +if [[ -n "$VIPM_TOML" ]]; then + VIPM_HELPER="/helpers/scripts/vipm-common/install-vipm-deps.sh" + if [[ ! -f "$VIPM_HELPER" ]]; then + echo "Error: VIPM helper not found at $VIPM_HELPER" + exit 1 + fi + HELPER_ARGS=(--vipm-toml "$VIPM_TOML") + if [[ -n "$VIPM_LOCK" ]]; then + HELPER_ARGS+=(--vipm-lock "$VIPM_LOCK") + fi + chmod +x "$VIPM_HELPER" + "$VIPM_HELPER" "${HELPER_ARGS[@]}" +fi + # Construct LabVIEWCLI command CLI_ARGS=( "-OperationName" "ExecuteBuildSpec" diff --git a/scripts/build-spec-docker-windows/BuildSpecDockerWindows.ps1 b/scripts/build-spec-docker-windows/BuildSpecDockerWindows.ps1 index c0cae1c3..5241a85f 100644 --- a/scripts/build-spec-docker-windows/BuildSpecDockerWindows.ps1 +++ b/scripts/build-spec-docker-windows/BuildSpecDockerWindows.ps1 @@ -85,7 +85,13 @@ param( [string]$DockerImage = "nationalinstruments/labview", [Parameter(Mandatory = $false)] - [string]$ImageTag = "2026q1-windows" + [string]$ImageTag = "2026q1-windows", + + [Parameter(Mandatory = $false)] + [string]$VipmToml = "", + + [Parameter(Mandatory = $false)] + [string]$VipmLock = "" ) Set-StrictMode -Version Latest @@ -175,6 +181,15 @@ try { $scriptArgs += "-Version", "`"$versionString`"" } + # Workspace is mounted at C:\workspace, so manifest paths are repo-relative. + if (-not [string]::IsNullOrWhiteSpace($VipmToml)) { + $scriptArgs += "-VipmToml", "`"C:\workspace\$VipmToml`"" + } + + if (-not [string]::IsNullOrWhiteSpace($VipmLock)) { + $scriptArgs += "-VipmLock", "`"C:\workspace\$VipmLock`"" + } + Write-Information "Executing build script in Windows Docker container..." -InformationAction Continue Write-Verbose "Script: $containerScriptPath $($scriptArgs -join ' ')" diff --git a/scripts/build-spec-docker-windows/build-spec.ps1 b/scripts/build-spec-docker-windows/build-spec.ps1 index 30b9bce6..4196d0b3 100644 --- a/scripts/build-spec-docker-windows/build-spec.ps1 +++ b/scripts/build-spec-docker-windows/build-spec.ps1 @@ -24,7 +24,13 @@ param( [string]$BuildSpecName = "", [Parameter(Mandatory = $false)] - [string]$Version = "" + [string]$Version = "", + + [Parameter(Mandatory = $false)] + [string]$VipmToml = "", + + [Parameter(Mandatory = $false)] + [string]$VipmLock = "" ) Set-StrictMode -Version Latest @@ -66,6 +72,18 @@ if ($Version) { Write-Host "Skipping build specification version set - using version from build spec(s)" } +# Install project dependencies from vipm.toml/vipm.lock before building +if ($VipmToml) { + $vipmHelper = "C:\actions\scripts\vipm-common\Invoke-VipmInstall.ps1" + if (-not (Test-Path $vipmHelper)) { + throw "VIPM helper not found at: $vipmHelper" + } + $helperParams = @{ VipmToml = $VipmToml } + if ($VipmLock) { $helperParams['VipmLock'] = $VipmLock } + & $vipmHelper @helperParams + if ($LASTEXITCODE -ne 0) { throw "VIPM dependency installation failed (exit code $LASTEXITCODE)." } +} + # Construct LabVIEWCLI command $cliArgs = @( '-OperationName', 'ExecuteBuildSpec' diff --git a/scripts/build-spec-github-hosted-windows/BuildSpecGithubHostedWindows.ps1 b/scripts/build-spec-github-hosted-windows/BuildSpecGithubHostedWindows.ps1 index b22f527b..740fe0b8 100644 --- a/scripts/build-spec-github-hosted-windows/BuildSpecGithubHostedWindows.ps1 +++ b/scripts/build-spec-github-hosted-windows/BuildSpecGithubHostedWindows.ps1 @@ -72,7 +72,13 @@ param( [int]$Build = -1, [Parameter(Mandatory = $false)] - [string]$Commit = "" + [string]$Commit = "", + + [Parameter(Mandatory = $false)] + [string]$VipmToml = "", + + [Parameter(Mandatory = $false)] + [string]$VipmLock = "" ) Set-StrictMode -Version Latest @@ -146,6 +152,18 @@ try { Write-Information "Skipping build specification version set " -InformationAction Continue } + # Install project dependencies from vipm.toml/vipm.lock before building + if ($VipmToml) { + $vipmHelper = Join-Path $PSScriptRoot '..' 'vipm-common' 'Invoke-VipmInstall.ps1' + if (-not (Test-Path $vipmHelper)) { + throw "VIPM helper not found at: $vipmHelper" + } + $helperParams = @{ VipmToml = (Resolve-Path $VipmToml).Path } + if ($VipmLock) { $helperParams['VipmLock'] = (Resolve-Path $VipmLock).Path } + & $vipmHelper @helperParams + if ($LASTEXITCODE -ne 0) { throw "VIPM dependency installation failed (exit code $LASTEXITCODE)." } + } + # Construct LabVIEWCLI command $cliArgs = @( '-OperationName', 'ExecuteBuildSpec' diff --git a/scripts/vipm-common/Invoke-VipmInstall.ps1 b/scripts/vipm-common/Invoke-VipmInstall.ps1 new file mode 100644 index 00000000..39b679b1 --- /dev/null +++ b/scripts/vipm-common/Invoke-VipmInstall.ps1 @@ -0,0 +1,143 @@ +<# +.SYNOPSIS + Resolve the VIPM CLI, verify it is new enough for vipm.toml/vipm.lock, and + install a project's dependencies from a manifest. + +.DESCRIPTION + Shared helper used by the Windows build-spec paths and apply-vipc. When a + manifest is supplied it resolves the `vipm` CLI (installing it on Windows if + missing), enforces a minimum version that supports vipm.toml/vipm.lock, + verifies vipm.lock is in sync (CI never writes it), and installs the + dependencies. A missing or too-old CLI is a hard error because dependencies + were explicitly requested; a missing or stale vipm.lock is also a hard + error — developers generate and commit it locally with `vipm lock`. + +.PARAMETER VipmToml + Path to the vipm.toml manifest (or the directory containing it). + +.PARAMETER VipmLock + Optional path to the vipm.lock file. Defaults to vipm.lock next to + VipmToml. Must already exist and be committed; verified via + `vipm lock --check`. + +.PARAMETER VipmInstallerUrl + Windows-only URL used to install VIPM when the CLI is not already present. + +.PARAMETER MinimumVipmVersion + Minimum VIPM CLI version required for vipm.toml/vipm.lock support, using the + CLI's own dotted MAJOR.MINOR[.PATCH] scheme (e.g. "25.3"), NOT a YYYY.Q year. + The real CLI reports versions like "26.3.0" (2-digit year, not 4-digit). + +.NOTES + vipm.lock is consumed automatically by `vipm install`; it is verified here, + not passed as an install source. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$VipmToml, + + [Parameter(Mandatory = $false)] + [string]$VipmLock = "", + + [Parameter(Mandatory = $false)] + [string]$VipmInstallerUrl = "https://packages.jki.net/vipm/preview/vipm-setup-latest-preview.exe", + + [Parameter(Mandatory = $false)] + [string]$MinimumVipmVersion = "25.3" +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$onWindows = ($PSVersionTable.PSVersion.Major -lt 6) -or $IsWindows + +# Returns the invocable VIPM CLI path, or $null if it cannot be located. +function Resolve-VipmCli { + $cmd = Get-Command 'vipm' -ErrorAction SilentlyContinue + if ($cmd) { return $cmd.Source } + if ($onWindows) { + $fallback = "C:\Program Files\JKI\VI Package Manager\support\vipm.exe" + if (Test-Path $fallback) { return $fallback } + } + return $null +} + +# Parses "vipm 26.3.0" (or `vipm version` output) into [version]. Real VIPM +# versions are plain dotted numbers (2-digit year, not YYYY.Q) with 2-4 parts, +# so capture the whole dotted run and let [version] compare part-by-part. +function Get-VipmVersion { + param([string]$Vipm) + $raw = '' + try { $raw = (& $Vipm --version 2>&1 | Out-String) } catch { $raw = '' } + if ($raw -notmatch '(\d+(?:\.\d+){1,3})') { + try { $raw = (& $Vipm version 2>&1 | Out-String) } catch { $raw = '' } + } + if ($raw -match '(\d+(?:\.\d+){1,3})') { + return [version]$Matches[1] + } + return $null +} + +$minVersion = [version]$MinimumVipmVersion +$vipm = Resolve-VipmCli + +if (-not $vipm) { + if (-not $onWindows) { + throw "VIPM CLI not found and automatic provisioning is only supported on Windows. Bake VIPM into your container image (FROM the NI LabVIEW image) or install it in the entrypoint, then retry. See https://docs.vipm.io/cli/docker/." + } + Write-Information "VIPM CLI not found. Installing from $VipmInstallerUrl..." -InformationAction Continue + $installer = Join-Path $env:TEMP "vipm-setup.exe" + Invoke-WebRequest -Uri $VipmInstallerUrl -OutFile $installer + $proc = Start-Process -FilePath $installer -ArgumentList "/quiet", "/norestart" -Wait -PassThru + if ($proc.ExitCode -ne 0) { + throw "VIPM installation failed with exit code $($proc.ExitCode)." + } + Remove-Item $installer -Force -ErrorAction SilentlyContinue + $vipm = Resolve-VipmCli + if (-not $vipm) { + throw "VIPM CLI still not found after installation." + } +} + +$version = Get-VipmVersion -Vipm $vipm +if (-not $version) { + throw "Unable to determine the VIPM CLI version from '$vipm'. A version >= $MinimumVipmVersion is required for vipm.toml/vipm.lock support." +} +if ($version -lt $minVersion) { + throw "VIPM $version does not support vipm.toml/vipm.lock. Version >= $MinimumVipmVersion is required." +} +Write-Information "Using VIPM $version at $vipm" -InformationAction Continue + +# Activation is only attempted when credentials are provided via environment. +if ($env:VIPM_SERIAL_NUMBER) { + Write-Information "Activating VIPM Pro..." -InformationAction Continue + & $vipm activate --serial-number $env:VIPM_SERIAL_NUMBER --name $env:VIPM_FULL_NAME --email $env:VIPM_EMAIL + if ($LASTEXITCODE -ne 0) { throw "VIPM activation failed (exit code $LASTEXITCODE)." } +} + +Write-Information "Refreshing VIPM package list..." -InformationAction Continue +& $vipm package-list-refresh +if ($LASTEXITCODE -ne 0) { throw "Failed to refresh VIPM package list (exit code $LASTEXITCODE)." } + +if (-not (Test-Path $VipmToml)) { throw "vipm.toml not found at '$VipmToml'." } + +# CI never writes vipm.lock; it must be generated and committed locally by a developer. +if (-not $VipmLock) { $VipmLock = Join-Path (Split-Path -Parent $VipmToml) 'vipm.lock' } +if (-not (Test-Path $VipmLock)) { + throw "vipm.lock not found at '$VipmLock'. Run 'vipm lock' next to vipm.toml locally and commit the result." +} +Write-Information "Verifying vipm.lock is in sync..." -InformationAction Continue +Push-Location (Split-Path -Parent $VipmToml) +try { + & $vipm lock --check + if ($LASTEXITCODE -ne 0) { throw "vipm.lock is out of sync with vipm.toml (vipm lock --check exit code $LASTEXITCODE). Run 'vipm lock' locally and commit the update." } +} finally { + Pop-Location +} +Write-Information "Installing dependencies from $VipmToml..." -InformationAction Continue +& $vipm install $VipmToml --no-dev +if ($LASTEXITCODE -ne 0) { throw "vipm install failed (exit code $LASTEXITCODE)." } + + +Write-Information "VIPM dependencies installed successfully." -InformationAction Continue diff --git a/scripts/vipm-common/New-VipmLock.ps1 b/scripts/vipm-common/New-VipmLock.ps1 new file mode 100644 index 00000000..c4649d64 --- /dev/null +++ b/scripts/vipm-common/New-VipmLock.ps1 @@ -0,0 +1,115 @@ +<# +.SYNOPSIS + Generates or refreshes vipm.lock from vipm.toml for CI artifact upload. + +.DESCRIPTION + Requires VIPM Community (public repo) or Pro (`vipm activate`). Never + commits or pushes; the caller (CI workflow) uploads the resulting + vipm.lock as a build artifact for a developer to download and commit. + +.PARAMETER VipmToml + Path to the vipm.toml manifest. + +.PARAMETER VipmInstallerUrl + Windows-only URL used to install VIPM when the CLI is not already present. + +.PARAMETER MinimumVipmVersion + Minimum VIPM CLI version required for vipm.toml/vipm.lock support, using the + CLI's own dotted MAJOR.MINOR[.PATCH] scheme (e.g. "25.3"), NOT a YYYY.Q year. + The real CLI reports versions like "26.3.0" (2-digit year, not 4-digit). +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$VipmToml, + + [Parameter(Mandatory = $false)] + [string]$VipmInstallerUrl = "https://packages.jki.net/vipm/preview/vipm-setup-latest-preview.exe", + + [Parameter(Mandatory = $false)] + [string]$MinimumVipmVersion = "25.3" +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +$onWindows = ($PSVersionTable.PSVersion.Major -lt 6) -or $IsWindows + +# Returns the invocable VIPM CLI path, or $null if it cannot be located. +function Resolve-VipmCli { + $cmd = Get-Command 'vipm' -ErrorAction SilentlyContinue + if ($cmd) { return $cmd.Source } + if ($onWindows) { + $fallback = "C:\Program Files\JKI\VI Package Manager\support\vipm.exe" + if (Test-Path $fallback) { return $fallback } + } + return $null +} + +# Parses "vipm 26.3.0" (or `vipm version` output) into [version]. Real VIPM +# versions are plain dotted numbers (2-digit year, not YYYY.Q) with 2-4 parts, +# so capture the whole dotted run and let [version] compare part-by-part. +function Get-VipmVersion { + param([string]$Vipm) + $raw = '' + try { $raw = (& $Vipm --version 2>&1 | Out-String) } catch { $raw = '' } + if ($raw -notmatch '(\d+(?:\.\d+){1,3})') { + try { $raw = (& $Vipm version 2>&1 | Out-String) } catch { $raw = '' } + } + if ($raw -match '(\d+(?:\.\d+){1,3})') { + return [version]$Matches[1] + } + return $null +} + +if (-not (Test-Path $VipmToml)) { throw "vipm.toml not found at '$VipmToml'." } + +$minVersion = [version]$MinimumVipmVersion +$vipm = Resolve-VipmCli + +if (-not $vipm) { + if (-not $onWindows) { + throw "VIPM CLI not found and automatic provisioning is only supported on Windows." + } + Write-Information "VIPM CLI not found. Installing from $VipmInstallerUrl..." -InformationAction Continue + $installer = Join-Path $env:TEMP "vipm-setup.exe" + Invoke-WebRequest -Uri $VipmInstallerUrl -OutFile $installer + $proc = Start-Process -FilePath $installer -ArgumentList "/quiet", "/norestart" -Wait -PassThru + if ($proc.ExitCode -ne 0) { throw "VIPM installation failed with exit code $($proc.ExitCode)." } + Remove-Item $installer -Force -ErrorAction SilentlyContinue + $vipm = Resolve-VipmCli + if (-not $vipm) { throw "VIPM CLI still not found after installation." } +} + +$version = Get-VipmVersion -Vipm $vipm +if (-not $version) { throw "Unable to determine the VIPM CLI version from '$vipm'." } +if ($version -lt $minVersion) { throw "VIPM $version does not support vipm.toml/vipm.lock. Version >= $MinimumVipmVersion is required." } +Write-Host "VIPM version: $version ($vipm)" + +if ($env:VIPM_SERIAL_NUMBER) { + Write-Information "Activating VIPM Pro..." -InformationAction Continue + & $vipm activate --serial-number $env:VIPM_SERIAL_NUMBER --name $env:VIPM_FULL_NAME --email $env:VIPM_EMAIL + if ($LASTEXITCODE -ne 0) { throw "VIPM activation failed (exit code $LASTEXITCODE)." } +} + +Write-Information "Refreshing VIPM package list..." -InformationAction Continue +& $vipm package-list-refresh +if ($LASTEXITCODE -ne 0) { throw "Failed to refresh VIPM package list (exit code $LASTEXITCODE)." } + +$tomlDir = Split-Path -Parent (Resolve-Path $VipmToml) +$lockPath = Join-Path $tomlDir 'vipm.lock' + +Write-Host "Lock generation command: vipm lock (cwd: $tomlDir)" +Push-Location $tomlDir +try { + & $vipm lock + $lockExitCode = $LASTEXITCODE +} finally { + Pop-Location +} +if ($lockExitCode -ne 0) { throw "vipm lock failed (exit code $lockExitCode)." } + +if (-not (Test-Path $lockPath)) { throw "vipm lock reported success but '$lockPath' was not created." } + +Write-Host "Final lock file path: $lockPath" +Write-Output $lockPath diff --git a/scripts/vipm-common/install-vipm-deps.sh b/scripts/vipm-common/install-vipm-deps.sh new file mode 100644 index 00000000..45befe23 --- /dev/null +++ b/scripts/vipm-common/install-vipm-deps.sh @@ -0,0 +1,86 @@ +#!/bin/bash +# Resolve the VIPM CLI, verify it supports vipm.toml/vipm.lock, and install a +# project's dependencies from a manifest. Used by the Linux container build path. +# A missing or too-old CLI is a hard error because dependencies were requested. + +set -euo pipefail + +VIPM_TOML="" +VIPM_LOCK="" +MIN_VERSION="25.3" + +while [[ $# -gt 0 ]]; do + case $1 in + --vipm-toml) + VIPM_TOML="$2"; shift 2 ;; + --vipm-lock) + VIPM_LOCK="$2"; shift 2 ;; + --min-version) + MIN_VERSION="$2"; shift 2 ;; + *) + echo "Unknown argument: $1"; exit 1 ;; + esac +done + +if [[ -z "$VIPM_TOML" ]]; then + echo "No vipm.toml provided; skipping dependency installation." + exit 0 +fi + +if ! command -v vipm >/dev/null 2>&1; then + echo "Error: VIPM CLI not found in container." + echo "The stock NI LabVIEW image does not include VIPM. Bake VIPM into a custom image (FROM the NI LabVIEW image) or install it in the entrypoint before building." + echo "See https://docs.vipm.io/cli/docker/." + exit 1 +fi + +# Real VIPM versions are plain dotted numbers (e.g. 26.3.0), not YYYY.Q - +# capture the whole dotted run (2-4 parts) so multi-part versions compare correctly. +VERSION_RAW="$(vipm --version 2>&1 || true)" +if ! echo "$VERSION_RAW" | grep -qoE '[0-9]+(\.[0-9]+){1,3}'; then + VERSION_RAW="$(vipm version 2>&1 || true)" +fi +VIPM_VERSION="$(echo "$VERSION_RAW" | grep -oE '[0-9]+(\.[0-9]+){1,3}' | head -n1 || true)" + +if [[ -z "$VIPM_VERSION" ]]; then + echo "Error: Unable to determine VIPM CLI version. Version >= $MIN_VERSION is required for vipm.toml/vipm.lock support." + exit 1 +fi + +# Version-aware compare (sort -V) handles multi-part dotted versions correctly; +# the smaller of the two strings sorts first, so MIN_VERSION sorting first (or +# tying) means VIPM_VERSION is new enough. +lowest="$(printf '%s\n%s\n' "$MIN_VERSION" "$VIPM_VERSION" | sort -V | head -n1)" +if [[ "$lowest" != "$MIN_VERSION" ]]; then + echo "Error: VIPM $VIPM_VERSION does not support vipm.toml/vipm.lock. Version >= $MIN_VERSION is required." + exit 1 +fi +echo "Using VIPM $VIPM_VERSION" + +# Activation is only attempted when credentials are provided via environment. +if [[ -n "${VIPM_SERIAL_NUMBER:-}" ]]; then + echo "Activating VIPM Pro..." + vipm activate --serial-number "$VIPM_SERIAL_NUMBER" --name "${VIPM_FULL_NAME:-}" --email "${VIPM_EMAIL:-}" +fi + +echo "Refreshing VIPM package list..." +vipm package-list-refresh + +if [[ ! -f "$VIPM_TOML" ]]; then + echo "Error: vipm.toml not found at $VIPM_TOML"; exit 1 +fi + +# Match Windows behavior: default to vipm.lock next to vipm.toml, fail if missing. +if [[ -z "$VIPM_LOCK" ]]; then + VIPM_LOCK="$(dirname "$VIPM_TOML")/vipm.lock" +fi +if [[ ! -f "$VIPM_LOCK" ]]; then + echo "Error: vipm.lock not found at $VIPM_LOCK. Run 'vipm lock' next to vipm.toml locally and commit the result." + exit 1 +fi +echo "Verifying vipm.lock is in sync..." +(cd "$(dirname "$VIPM_TOML")" && vipm lock --check) + +echo "Installing dependencies from $VIPM_TOML..." +vipm install "$VIPM_TOML" --no-dev +echo "VIPM dependencies installed successfully." From fdbac81af2ac8e7721d07f9cc8522516c2bb5c23 Mon Sep 17 00:00:00 2001 From: Amrutha G Date: Tue, 8 Sep 2026 14:48:48 +0530 Subject: [PATCH 2/3] Install VIPM automatically in Linux containers --- scripts/vipm-common/install-vipm-deps.sh | 25 +++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/scripts/vipm-common/install-vipm-deps.sh b/scripts/vipm-common/install-vipm-deps.sh index 45befe23..be4b70fb 100644 --- a/scripts/vipm-common/install-vipm-deps.sh +++ b/scripts/vipm-common/install-vipm-deps.sh @@ -1,13 +1,15 @@ #!/bin/bash -# Resolve the VIPM CLI, verify it supports vipm.toml/vipm.lock, and install a -# project's dependencies from a manifest. Used by the Linux container build path. -# A missing or too-old CLI is a hard error because dependencies were requested. +# Resolve the VIPM CLI (installing it via .deb if missing), verify it supports +# vipm.toml/vipm.lock, and install a project's dependencies from a manifest. +# Used by the Linux container build path. A too-old CLI is a hard error because +# dependencies were explicitly requested. set -euo pipefail VIPM_TOML="" VIPM_LOCK="" MIN_VERSION="25.3" +VIPM_DEB_URL="https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb" while [[ $# -gt 0 ]]; do case $1 in @@ -28,10 +30,19 @@ if [[ -z "$VIPM_TOML" ]]; then fi if ! command -v vipm >/dev/null 2>&1; then - echo "Error: VIPM CLI not found in container." - echo "The stock NI LabVIEW image does not include VIPM. Bake VIPM into a custom image (FROM the NI LabVIEW image) or install it in the entrypoint before building." - echo "See https://docs.vipm.io/cli/docker/." - exit 1 + echo "VIPM CLI not found in container; installing from $VIPM_DEB_URL..." + apt-get update + apt-get install -y wget + wget --no-check-certificate -O /tmp/vipm.deb "$VIPM_DEB_URL" + dpkg -i /tmp/vipm.deb + vipm --version + rm -f /tmp/vipm.deb + + if ! command -v vipm >/dev/null 2>&1; then + echo "Error: VIPM CLI still not found after installation." + exit 1 + fi + echo "VIPM installed: $(vipm --version)" fi # Real VIPM versions are plain dotted numbers (e.g. 26.3.0), not YYYY.Q - From 4f047f19484e5a36cc1594d3448a4c8b90219d2a Mon Sep 17 00:00:00 2001 From: Amrutha G Date: Wed, 9 Sep 2026 12:07:10 +0530 Subject: [PATCH 3/3] removed vipc paths --- .github/workflows/apply-vipc-self-hosted.json | 4 ++-- .github/workflows/apply-vipc-self-hosted.yml | 2 +- .github/workflows/ci.yml | 7 ++++++- requirements.json | 4 ++-- tests/pester/ApplyVipc.Workflow.Tests.ps1 | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/apply-vipc-self-hosted.json b/.github/workflows/apply-vipc-self-hosted.json index bfe6d0f9..bf3ab4b0 100644 --- a/.github/workflows/apply-vipc-self-hosted.json +++ b/.github/workflows/apply-vipc-self-hosted.json @@ -18,11 +18,11 @@ "vip_lv_version": "2021", "supported_bitness": "64", "relative_path": ".", - "vipc_path": "scripts/apply-vipc/runner_dependencies.vipc", + "vipm_toml": "scripts/apply-vipc/vipm.toml", "dry_run": true } } ] } } -} +} \ No newline at end of file diff --git a/.github/workflows/apply-vipc-self-hosted.yml b/.github/workflows/apply-vipc-self-hosted.yml index efe67fae..a8db6099 100644 --- a/.github/workflows/apply-vipc-self-hosted.yml +++ b/.github/workflows/apply-vipc-self-hosted.yml @@ -15,5 +15,5 @@ jobs: vip_lv_version: '2021' supported_bitness: '64' relative_path: '.' - vipc_path: 'scripts/apply-vipc/runner_dependencies.vipc' + vipm_toml: 'scripts/apply-vipc/vipm.toml' dry_run: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ff34bb29..1891650f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,6 @@ jobs: - run: npm run link:check - run: npm run derive:registry - run: git diff --exit-code -- dispatchers.json - - run: npm run check:traceability ps-ci: needs: release-check strategy: @@ -56,6 +55,7 @@ jobs: runs-on: self-hosted-windows-lv runner_type: default runs-on: ${{ matrix.runs-on }} + timeout-minutes: 30 env: RUNNER_TYPE: ${{ matrix.runner_type }} steps: @@ -85,6 +85,10 @@ jobs: run: | if (-not (Get-Module -ListAvailable -Name Pester | Where-Object { $_.Version -ge [Version]'5.7.1' })) { + if (-not (Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction SilentlyContinue)) { + Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser + } + Set-PSRepository -Name PSGallery -InstallationPolicy Trusted Remove-Module Pester -ErrorAction SilentlyContinue Install-Module -Name Pester -RequiredVersion 5.7.1 -Scope CurrentUser -Force -SkipPublisherCheck } @@ -132,6 +136,7 @@ jobs: DISPATCHER_REGISTRY: dispatchers.json EVIDENCE_DIR: artifacts/evidence - run: npx tsx scripts/generate-traceability-matrix.ts + - run: npm run check:traceability - run: cat artifacts/linux/traceability-matrix.md >> "$GITHUB_STEP_SUMMARY" - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 if: ${{ (success() || failure()) && !cancelled() }} diff --git a/requirements.json b/requirements.json index 6f279c99..6a6c2b2f 100644 --- a/requirements.json +++ b/requirements.json @@ -57,7 +57,7 @@ }, { "id": "REQ-006", - "description": "Workflow tests the composite action defined in apply-vipc/action.yml with minimum_supported_lv_version '2021', vip_lv_version '2021', supported_bitness '64', relative_path '.', and vipc_path 'scripts/apply-vipc/runner_dependencies.vipc' on the GitHub-hosted Ubuntu runner labeled ubuntu-latest with dry_run true.", + "description": "Workflow tests the composite action defined in apply-vipc/action.yml with minimum_supported_lv_version '2021', vip_lv_version '2021', supported_bitness '64', relative_path '.', and vipm_toml 'scripts/apply-vipc/vipm.toml' on the GitHub-hosted Ubuntu runner labeled ubuntu-latest with dry_run true.", "runner": "ubuntu-latest", "tests": [ "ApplyVipc.DryRunTrue.Workflow" @@ -428,4 +428,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/tests/pester/ApplyVipc.Workflow.Tests.ps1 b/tests/pester/ApplyVipc.Workflow.Tests.ps1 index bc9da11b..ccd992c0 100644 --- a/tests/pester/ApplyVipc.Workflow.Tests.ps1 +++ b/tests/pester/ApplyVipc.Workflow.Tests.ps1 @@ -28,7 +28,7 @@ Describe 'ApplyVipc.DryRunTrue.Workflow' { $applyStep.with.vip_lv_version | Should -Be '2021' $applyStep.with.supported_bitness | Should -Be '64' $applyStep.with.relative_path | Should -Be '.' - $applyStep.with.vipc_path | Should -Be 'scripts/apply-vipc/runner_dependencies.vipc' + $applyStep.with.vipm_toml | Should -Be 'scripts/apply-vipc/vipm.toml' $applyStep.with.dry_run | Should -Be $true } }