diff --git a/.github/workflows/reusable-vipm-lock.yml b/.github/workflows/reusable-vipm-lock.yml new file mode 100644 index 00000000..de2d0d20 --- /dev/null +++ b/.github/workflows/reusable-vipm-lock.yml @@ -0,0 +1,79 @@ +name: Reusable - Refresh VIPM Lock + +on: + workflow_call: + inputs: + working_directory: + description: 'Path (relative to the caller repo root) containing vipm.toml.' + required: true + type: string + labview_version: + description: 'LabVIEW version (YYYY) matching the [project] section of vipm.toml.' + required: true + type: string + labview_bitness: + description: '"32" or "64" bitness matching the [project] section of vipm.toml.' + required: true + type: string + check_only: + description: 'If true, verifies an existing vipm.lock or generates the initial lock when absent.' + required: false + type: boolean + default: false + base_branch: + description: 'Target branch for the generated pull request.' + required: true + type: string + pr_branch: + description: 'Branch name to push vipm.lock updates to.' + required: false + type: string + default: 'automation/vipm-lock-refresh' + pr_labels: + description: 'Comma-separated labels to apply to the generated PR.' + required: false + type: string + default: 'dependencies' + secrets: + VIPM_SERIAL_NUMBER: + required: false + VIPM_FULL_NAME: + required: false + VIPM_EMAIL: + required: false + +jobs: + refresh-vipm-lock: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 + - uses: ni/open-source/refresh-vipm-lock@users/amrutha/vipm-lock-refresh-and-dependency-update + with: + working_directory: ${{ inputs.working_directory }} + labview_version: ${{ inputs.labview_version }} + labview_bitness: ${{ inputs.labview_bitness }} + check_only: ${{ inputs.check_only }} + vipm_serial_number: ${{ secrets.VIPM_SERIAL_NUMBER }} + vipm_full_name: ${{ secrets.VIPM_FULL_NAME }} + vipm_email: ${{ secrets.VIPM_EMAIL }} + - name: Upload vipm.lock artifact + if: ${{ inputs.check_only }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 + with: + name: vipm-lock + path: ${{ inputs.working_directory }}/vipm.lock + if-no-files-found: error + - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 + if: ${{ !inputs.check_only }} + with: + commit-message: 'chore(deps): refresh vipm.lock' + title: 'chore(deps): refresh vipm.lock' + body: | + Automated `vipm.lock` refresh generated by `ni/open-source`'s reusable + `reusable-vipm-lock.yml` workflow. + + Review the `vipm.lock` diff before merging. + base: ${{ inputs.base_branch }} + branch: ${{ inputs.pr_branch }} + add-paths: ${{ inputs.working_directory }}/vipm.lock + labels: ${{ inputs.pr_labels }} \ No newline at end of file diff --git a/.github/workflows/reusable-vipm-update.yml b/.github/workflows/reusable-vipm-update.yml new file mode 100644 index 00000000..c344b751 --- /dev/null +++ b/.github/workflows/reusable-vipm-update.yml @@ -0,0 +1,100 @@ +name: Reusable - Update VIPM Dependencies + +on: + workflow_call: + inputs: + working_directory: + description: 'Path (relative to the caller repo root) containing vipm.toml.' + required: true + type: string + labview_version: + description: 'LabVIEW version (YYYY) matching the [project] section of vipm.toml.' + required: true + type: string + labview_bitness: + description: '"32" or "64" bitness matching the [project] section of vipm.toml.' + required: true + type: string + base_branch: + description: 'Target branch for the generated pull request in the caller repository.' + required: true + type: string + pr_branch: + description: 'Branch name to push dependency updates to.' + required: false + type: string + default: 'automation/vipm-dependency-update' + pr_labels: + description: 'Comma-separated labels to apply to the generated PR.' + required: false + type: string + default: 'dependencies' + secrets: + VIPM_SERIAL_NUMBER: + required: false + VIPM_FULL_NAME: + required: false + VIPM_EMAIL: + required: false + + workflow_dispatch: + inputs: + working_directory: + description: 'Path (relative to this repository root) containing vipm.toml.' + required: true + type: string + labview_version: + description: 'LabVIEW version (YYYY).' + required: true + type: string + labview_bitness: + description: '"32" or "64" bitness.' + required: true + type: string + base_branch: + description: "Optional target branch; defaults to this repository's default branch." + required: false + type: string + pr_branch: + description: 'Branch name to push dependency updates to.' + required: false + type: string + default: 'automation/vipm-dependency-update' + pr_labels: + description: 'Comma-separated labels to apply to the generated PR.' + required: false + type: string + default: 'dependencies' + +permissions: + contents: write + pull-requests: write + +jobs: + update-vipm-dependencies: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 + - uses: ni/open-source/update-vipm-dependencies@users/amrutha/vipm-lock-refresh-and-dependency-update + with: + working_directory: ${{ inputs.working_directory }} + labview_version: ${{ inputs.labview_version }} + labview_bitness: ${{ inputs.labview_bitness }} + vipm_serial_number: ${{ secrets.VIPM_SERIAL_NUMBER }} + vipm_full_name: ${{ secrets.VIPM_FULL_NAME }} + vipm_email: ${{ secrets.VIPM_EMAIL }} + - uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 + with: + commit-message: 'chore(deps): update VIPM package dependencies' + title: 'chore(deps): update VIPM package dependencies' + body: | + Automated dependency update generated by `ni/open-source`'s reusable + `reusable-vipm-update.yml` workflow. + + Review the `vipm.toml` / `vipm.lock` diff before merging. + base: ${{ inputs.base_branch || github.event.repository.default_branch }} + branch: ${{ inputs.pr_branch }} + add-paths: | + ${{ inputs.working_directory }}/vipm.toml + ${{ inputs.working_directory }}/vipm.lock + labels: ${{ inputs.pr_labels }} \ No newline at end of file diff --git a/actions/OpenSourceActions.psd1 b/actions/OpenSourceActions.psd1 index a9e703b0..5aa36b95 100644 --- a/actions/OpenSourceActions.psd1 +++ b/actions/OpenSourceActions.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'OpenSourceActions.psm1' - ModuleVersion = '1.0.0' + ModuleVersion = '1.1.1' GUID = '8c0a64c5-6a52-4d7e-9f74-8f79f21f1b2c' Author = 'LabVIEW Community CI/CD' CompanyName = 'LabVIEW Community' @@ -25,6 +25,7 @@ 'Invoke-MissingInProject' 'Invoke-ModifyVIPBDisplayInfo' 'Invoke-PrepareLabVIEWSource' + 'Invoke-RefreshVipmLock' 'Invoke-RenameFile' 'Invoke-RestoreSetupLVSource' 'Invoke-RevertDevelopmentMode' @@ -34,6 +35,7 @@ 'Invoke-SetupLabview' 'Invoke-SetupLunit' 'Invoke-SetupNipm' + 'Invoke-UpdateVipmDependencies' 'Invoke-ViaLvDocker' ) @@ -41,6 +43,7 @@ PSData = @{ ReleaseNotes = @( '1.0.0 - Initial release: adapters for apply-vipc, build-lvlibp, missing-in-project, run-unit-tests; Format-UnitTestReport helper; discovery flags; DryRun; cross-platform g-cli support.' + '1.1.1 - Fix: update-vipm-dependencies now fails the job (instead of warning and continuing) when any package cannot be resolved/updated, so a partial dependency bump never reaches vipm.lock or a PR.' ) } } diff --git a/actions/OpenSourceActions.psm1 b/actions/OpenSourceActions.psm1 index fd12abd9..01a90c5a 100644 --- a/actions/OpenSourceActions.psm1 +++ b/actions/OpenSourceActions.psm1 @@ -776,6 +776,117 @@ function Invoke-SetupNipm { return $result } +# Generates or checks vipm.lock from vipm.toml using the VIPM CLI in a Linux Docker container. +# WorkingDirectory: Path (relative to the repo root) containing vipm.toml. +# LabVIEWVersion: LabVIEW version (YYYY) matching the [project] section of vipm.toml. +# LabVIEWBitness: "32" or "64" bitness matching the [project] section of vipm.toml. +# CheckOnly: If set, checks an existing vipm.lock or generates the initial lock when absent. +# VipmSerialNumber: VIPM Pro serial number (omit to skip activation). +# VipmFullName: Name used for VIPM Pro activation. +# VipmEmail: Email used for VIPM Pro activation. +# VipmDebUrl: URL for the VIPM Linux .deb package. +# DockerImage: Docker image name (default: "nationalinstruments/labview"). +# ImageTag: Docker image tag (default: "latest-linux"). +# DryRun: If set, prints the command instead of executing it. +function Invoke-RefreshVipmLock { + [CmdletBinding()] + param( + [Parameter(Mandatory)] [string] $WorkingDirectory, + [string] $LabVIEWVersion, + [string] $LabVIEWBitness, + [switch] $CheckOnly, + [Parameter()] [string] $VipmSerialNumber = "", + [Parameter()] [string] $VipmFullName = "", + [Parameter()] [string] $VipmEmail = "", + [Parameter()] [string] $VipmDebUrl = "https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb", + [Parameter()] [string] $DockerImage = "nationalinstruments/labview", + [Parameter()] [string] $ImageTag = "latest-linux", + [switch] $DryRun + ) + Write-Information "Invoking RefreshVipmLock" -InformationAction Continue + + if (-not $DryRun) { + if ([string]::IsNullOrWhiteSpace($LabVIEWVersion) -or [string]::IsNullOrWhiteSpace($LabVIEWBitness)) { + throw 'LabVIEWVersion and LabVIEWBitness are required unless -DryRun is specified.' + } + if ($LabVIEWBitness -notin @('32', '64')) { + throw "Unsupported LabVIEW bitness: $LabVIEWBitness" + } + } + + $result = Invoke-OpenSourceActionScript ` + -ScriptSegments @('refresh-vipm-lock', 'RefreshVipmLock.ps1') ` + -Arguments @{ + WorkingDirectory = $WorkingDirectory + LabVIEWVersion = $LabVIEWVersion + LabVIEWBitness = $LabVIEWBitness + CheckOnly = $CheckOnly + VipmSerialNumber = $VipmSerialNumber + VipmFullName = $VipmFullName + VipmEmail = $VipmEmail + VipmDebUrl = $VipmDebUrl + DockerImage = $DockerImage + ImageTag = $ImageTag + } ` + -DryRun:$DryRun + + return $result +} + +# Bumps every dependency in vipm.toml to its latest available version and regenerates vipm.lock. +# WorkingDirectory: Path (relative to the repo root) containing vipm.toml. +# LabVIEWVersion: LabVIEW version (YYYY) matching the [project] section of vipm.toml. +# LabVIEWBitness: "32" or "64" bitness matching the [project] section of vipm.toml. +# VipmSerialNumber: VIPM Pro serial number (`vipm add` requires Community or Professional edition). +# VipmFullName: Name used for VIPM Pro activation. +# VipmEmail: Email used for VIPM Pro activation. +# VipmDebUrl: URL for the VIPM Linux .deb package. +# DockerImage: Docker image name (default: "nationalinstruments/labview"). +# ImageTag: Docker image tag (default: "latest-linux"). +# DryRun: If set, prints the command instead of executing it. +function Invoke-UpdateVipmDependencies { + [CmdletBinding()] + param( + [Parameter(Mandatory)] [string] $WorkingDirectory, + [string] $LabVIEWVersion, + [string] $LabVIEWBitness, + [Parameter()] [string] $VipmSerialNumber = "", + [Parameter()] [string] $VipmFullName = "", + [Parameter()] [string] $VipmEmail = "", + [Parameter()] [string] $VipmDebUrl = "https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb", + [Parameter()] [string] $DockerImage = "nationalinstruments/labview", + [Parameter()] [string] $ImageTag = "latest-linux", + [switch] $DryRun + ) + Write-Information "Invoking UpdateVipmDependencies" -InformationAction Continue + + if (-not $DryRun) { + if ([string]::IsNullOrWhiteSpace($LabVIEWVersion) -or [string]::IsNullOrWhiteSpace($LabVIEWBitness)) { + throw 'LabVIEWVersion and LabVIEWBitness are required unless -DryRun is specified.' + } + if ($LabVIEWBitness -notin @('32', '64')) { + throw "Unsupported LabVIEW bitness: $LabVIEWBitness" + } + } + + $result = Invoke-OpenSourceActionScript ` + -ScriptSegments @('update-vipm-dependencies', 'UpdateVipmDependencies.ps1') ` + -Arguments @{ + WorkingDirectory = $WorkingDirectory + LabVIEWVersion = $LabVIEWVersion + LabVIEWBitness = $LabVIEWBitness + VipmSerialNumber = $VipmSerialNumber + VipmFullName = $VipmFullName + VipmEmail = $VipmEmail + VipmDebUrl = $VipmDebUrl + DockerImage = $DockerImage + ImageTag = $ImageTag + } ` + -DryRun:$DryRun + + return $result +} + # Runs VI Analyzer tests using LabVIEW Docker container. # ConfigPath: Path to VI Analyzer configuration file (.viancfg) or LabVIEW files (.vi, .ctl, .llb). If empty, generates from changed files. # TemplatePath: Path to .viancfg template (required when generating config dynamically). diff --git a/dispatchers.json b/dispatchers.json index 126b4f7a..235b5e24 100644 --- a/dispatchers.json +++ b/dispatchers.json @@ -728,6 +728,72 @@ } } }, + "Invoke-RefreshVipmLock": { + "description": "Generates or checks vipm.lock from vipm.toml using the VIPM CLI in a Linux Docker container. WorkingDirectory: Path (relative to the repo root) containing vipm.toml. LabVIEWVersion: LabVIEW version (YYYY) matching the [project] section of vipm.toml. LabVIEWBitness: \"32\" or \"64\" bitness matching the [project] section of vipm.toml. CheckOnly: If set, checks an existing vipm.lock or generates the initial lock when absent. VipmSerialNumber: VIPM Pro serial number (omit to skip activation). VipmFullName: Name used for VIPM Pro activation. VipmEmail: Email used for VIPM Pro activation. VipmDebUrl: URL for the VIPM Linux .deb package. DockerImage: Docker image name (default: \"nationalinstruments/labview\"). ImageTag: Docker image tag (default: \"latest-linux\"). DryRun: If set, prints the command instead of executing it.", + "parameters": { + "CheckOnly": { + "type": "boolean", + "required": false, + "description": "If set, checks an existing vipm" + }, + "DockerImage": { + "type": "string", + "required": false, + "default": "nationalinstruments/labview", + "description": "Docker image name (default: \"nationalinstruments/labview\")" + }, + "DryRun": { + "type": "boolean", + "required": false, + "description": "If set, prints the command instead of executing it" + }, + "ImageTag": { + "type": "string", + "required": false, + "default": "latest-linux", + "description": "Docker image tag (default: \"latest-linux\")" + }, + "LabVIEWBitness": { + "type": "string", + "required": false, + "description": "\"32\" or \"64\" bitness matching the [project] section of vipm" + }, + "LabVIEWVersion": { + "type": "string", + "required": false, + "description": "LabVIEW version (YYYY) matching the [project] section of vipm" + }, + "VipmDebUrl": { + "type": "string", + "required": false, + "default": "https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb", + "description": "URL for the VIPM Linux" + }, + "VipmEmail": { + "type": "string", + "required": false, + "default": "", + "description": "Email used for VIPM Pro activation" + }, + "VipmFullName": { + "type": "string", + "required": false, + "default": "", + "description": "Name used for VIPM Pro activation" + }, + "VipmSerialNumber": { + "type": "string", + "required": false, + "default": "", + "description": "VIPM Pro serial number (omit to skip activation)" + }, + "WorkingDirectory": { + "type": "string", + "required": true, + "description": "Path (relative to the repo root) containing vipm" + } + } + }, "Invoke-RenameFile": { "description": "Renames a file on disk. CurrentFilename: Existing path to the file. NewFilename: New path for the file. DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", "parameters": { @@ -963,6 +1029,67 @@ } } }, + "Invoke-UpdateVipmDependencies": { + "description": "Bumps every dependency in vipm.toml to its latest available version and regenerates vipm.lock. WorkingDirectory: Path (relative to the repo root) containing vipm.toml. LabVIEWVersion: LabVIEW version (YYYY) matching the [project] section of vipm.toml. LabVIEWBitness: \"32\" or \"64\" bitness matching the [project] section of vipm.toml. VipmSerialNumber: VIPM Pro serial number (`vipm add` requires Community or Professional edition). VipmFullName: Name used for VIPM Pro activation. VipmEmail: Email used for VIPM Pro activation. VipmDebUrl: URL for the VIPM Linux .deb package. DockerImage: Docker image name (default: \"nationalinstruments/labview\"). ImageTag: Docker image tag (default: \"latest-linux\"). DryRun: If set, prints the command instead of executing it.", + "parameters": { + "DockerImage": { + "type": "string", + "required": false, + "default": "nationalinstruments/labview", + "description": "Docker image name (default: \"nationalinstruments/labview\")" + }, + "DryRun": { + "type": "boolean", + "required": false, + "description": "If set, prints the command instead of executing it" + }, + "ImageTag": { + "type": "string", + "required": false, + "default": "latest-linux", + "description": "Docker image tag (default: \"latest-linux\")" + }, + "LabVIEWBitness": { + "type": "string", + "required": false, + "description": "\"32\" or \"64\" bitness matching the [project] section of vipm" + }, + "LabVIEWVersion": { + "type": "string", + "required": false, + "description": "LabVIEW version (YYYY) matching the [project] section of vipm" + }, + "VipmDebUrl": { + "type": "string", + "required": false, + "default": "https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb", + "description": "URL for the VIPM Linux" + }, + "VipmEmail": { + "type": "string", + "required": false, + "default": "", + "description": "Email used for VIPM Pro activation" + }, + "VipmFullName": { + "type": "string", + "required": false, + "default": "", + "description": "Name used for VIPM Pro activation" + }, + "VipmSerialNumber": { + "type": "string", + "required": false, + "default": "", + "description": "VIPM Pro serial number (`vipm add` requires Community or Professional edition)" + }, + "WorkingDirectory": { + "type": "string", + "required": true, + "description": "Path (relative to the repo root) containing vipm" + } + } + }, "Invoke-ViaLvDocker": { "description": "Runs VI Analyzer tests using LabVIEW Docker container. ConfigPath: Path to VI Analyzer configuration file (.viancfg) or LabVIEW files (.vi, .ctl, .llb). If empty, generates from changed files. TemplatePath: Path to .viancfg template (required when generating config dynamically). BaseBranch: Branch to compare against for changed files (used when generating config). LabviewVersion: LabVIEW Docker image version tag. DockerImage: Full Docker image name. DryRun: If set, prints the command instead of executing it. gcliPath: Optional path prepended to PATH for locating the g CLI.", "parameters": { diff --git a/refresh-vipm-lock/action.yml b/refresh-vipm-lock/action.yml new file mode 100644 index 00000000..0c53d9b3 --- /dev/null +++ b/refresh-vipm-lock/action.yml @@ -0,0 +1,73 @@ +name: 'Refresh VIPM Lock' +description: 'Generates or checks vipm.lock from vipm.toml using the VIPM CLI inside a Linux Docker container.' +inputs: + working_directory: + description: 'Path (relative to the caller repo root) containing vipm.toml.' + required: true + labview_version: + description: 'LabVIEW version (YYYY) matching the [project] section of vipm.toml.' + required: true + labview_bitness: + description: '"32" or "64" bitness matching the [project] section of vipm.toml.' + required: true + check_only: + description: 'If true, checks an existing vipm.lock or generates the initial lock when absent.' + default: 'false' + required: false + vipm_serial_number: + description: 'VIPM Pro serial number (pass from a secret in the caller).' + required: false + vipm_full_name: + description: 'Name used for VIPM Pro activation.' + required: false + vipm_email: + description: 'Email used for VIPM Pro activation.' + required: false + vipm_deb_url: + description: 'Override URL for the VIPM Linux .deb package.' + default: 'https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb' + required: false + docker_image: + description: 'Docker image name.' + default: 'nationalinstruments/labview' + required: false + image_tag: + description: 'Docker image tag.' + default: 'latest-linux' + 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 refresh-vipm-lock + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + $args = @{ + WorkingDirectory = '${{ inputs.working_directory }}' + LabVIEWVersion = '${{ inputs.labview_version }}' + LabVIEWBitness = '${{ inputs.labview_bitness }}' + VipmSerialNumber = '${{ inputs.vipm_serial_number }}' + VipmFullName = '${{ inputs.vipm_full_name }}' + VipmEmail = '${{ inputs.vipm_email }}' + VipmDebUrl = '${{ inputs.vipm_deb_url }}' + DockerImage = '${{ inputs.docker_image }}' + ImageTag = '${{ inputs.image_tag }}' + } + if ('${{ inputs.check_only }}' -eq 'true') { $args['CheckOnly'] = $true } + $params = @{ + ActionName = 'refresh-vipm-lock' + Args = $args + LogLevel = '${{ inputs.log_level }}' + } + if ('${{ inputs.dry_run }}' -eq 'true') { $params['DryRun'] = $true } + $script = Join-Path $env:GITHUB_ACTION_PATH '..' 'actions' 'common-dispatch.ps1' + & $script @params + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } diff --git a/requirements.json b/requirements.json index 6f279c99..ab7ecd13 100644 --- a/requirements.json +++ b/requirements.json @@ -317,6 +317,22 @@ "BuildSpecGithubHostedWindows.Workflow.Tests" ] }, + { + "id": "REQ-043", + "description": "Workflow tests the composite action defined in refresh-vipm-lock/action.yml on the GitHub-hosted Ubuntu runner labeled ubuntu-latest.", + "runner": "ubuntu-latest", + "tests": [ + "RefreshVipmLock.Workflow.Tests" + ] + }, + { + "id": "REQ-044", + "description": "Workflow tests the composite action defined in update-vipm-dependencies/action.yml on the GitHub-hosted Ubuntu runner labeled ubuntu-latest.", + "runner": "ubuntu-latest", + "tests": [ + "UpdateVipmDependencies.Workflow.Tests" + ] + }, { "id": "REQIE-001", "description": "After checking out the LabVIEW icon editor repository, PreSequence: The sequencer shall enumerate and record the build matrix used by the workflow (LabVIEW versions and bitness). Acceptance: a 'matrix.json' file exists listing each tuple {\"lv-version\": \"2021\"|\"2023\", \"bitness\": \"32\"|\"64\"} with at least [ [\"2021\",\"32\"], [\"2021\",\"64\"], [\"2023\",\"64\"] ]. g-cli is expected at 'C:\\Program Files\\G-CLI\\bin\\g-cli.exe'.", @@ -428,4 +444,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/scripts/apply-vipc/vipm.lock b/scripts/apply-vipc/vipm.lock new file mode 100644 index 00000000..6e6acd8c --- /dev/null +++ b/scripts/apply-vipc/vipm.lock @@ -0,0 +1,186 @@ +# It is not intended for manual editing. + +version = 2 +revision = 0 +updated-at = "2026-09-28T11:20:23.409677154Z" +requires-labview = "2021" +labview-bitness = 64 + +[[vipm.repo]] +name = "VIPM Community" +uri = "http://www.jkisoft.com/packages" + +[[package]] +name = "astemes_lib_lunit" +version = "1.10.7.3" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:0eec735c67849e00bacb792d90030318" + +[[package]] +name = "hse_lib_git_api" +version = "2.3.4.176" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:af3256375655bdb2af8503025a754da2" + +[[package]] +name = "jki_lib_serialization" +version = "1.0.1.14" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:51997ae9c8110c50bec7d725cdf1598f" + +[[package]] +name = "jki_lib_state_machine" +version = "2024.0.3.23" +manager = "vipm" +dependencies = ["jki_rsc_toolkits_palette"] +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:58d05fd50ecd54c4f1bfc05d47064f61" + +[[package]] +name = "jki_lib_unicode" +version = "1.0.0.7" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:5b478d1b5b86bf9d3366b55515b2d520" + +[[package]] +name = "jki_lib_vipm_api" +version = "2020.0.3.80" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:cb505625a4ff64539096f041ad32f687" + +[[package]] +name = "jki_rsc_toolkits_palette" +version = "1.1-1" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:d8e12776ee5532544b44cc7ab43045f8" + +[[package]] +name = "oglib_array" +version = "6.0.1.20" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:a56326241d08d49c74b7c4dc47eef591" + +[[package]] +name = "oglib_error" +version = "6.0.0.26" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:2e202920a5ca2b6fc1db1705924ba90c" + +[[package]] +name = "oglib_file" +version = "6.0.2.28" +manager = "vipm" +dependencies = [ + "oglib_array", + "oglib_error", +] +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:55f6536972da75ee7f1ab59fd72f1ace" + +[[package]] +name = "oglib_lvdata" +version = "6.0.0.45" +manager = "vipm" +dependencies = ["oglib_error"] +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:7ac1df48c85dc6fe8f2b6ed50706d5c5" + +[[package]] +name = "oglib_lvzip" +version = "5.0.9-1" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:777dcc49eebb8062cd69eb0db806df1a" + +[[package]] +name = "sas_workshops_lib_lunit_for_g_cli" +version = "1.1.1.54" +manager = "vipm" +dependencies = [ + "astemes_lib_lunit", + "wiresmith_technology_lib_g_cli", +] +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:58fa03e58052b1813d209fc92a748640" + +[[package]] +name = "sas_workshops_lib_lvbuildspec_for_g_cli" +version = "1.2.1.104" +manager = "vipm" +dependencies = ["wiresmith_technology_lib_g_cli"] +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:52e086b74929d6e1da3bbdaa6238ebc1" + +[[package]] +name = "sas_workshops_lib_vipb_builder_for_g_cli" +version = "1.1.6.46" +manager = "vipm" +dependencies = [ + "jki_lib_vipm_api", + "wiresmith_technology_lib_g_cli", +] +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:b2fddfd5015cbf48a2fd433278c0776f" + +[[package]] +name = "wiresmith_technology_lib_g_cli" +version = "3.0.1.98" +manager = "vipm" +resolution-source = "repo" + +[[package.source]] +repo = "VIPM Community" +checksum = "md5:afd65a73b9c5719d91830db7a021d111" diff --git a/scripts/apply-vipc/vipm.toml b/scripts/apply-vipc/vipm.toml new file mode 100644 index 00000000..bd6a7334 --- /dev/null +++ b/scripts/apply-vipc/vipm.toml @@ -0,0 +1,22 @@ +[project] +name = "runner-dependencies" +labview-version = 2021 +labview-bitness = 64 + +[dependencies] +astemes_lib_lunit = "1.10.7.3" +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_lib_vipm_api = "2020.0.3.80" +jki_rsc_toolkits_palette = "1.1-1" +oglib_array = "6.0.1.20" +oglib_error = "6.0.0.26" +oglib_file = "6.0.2.28" +oglib_lvdata = "6.0.0.45" +oglib_lvzip = "5.0.9-1" +sas_workshops_lib_lunit_for_g_cli = "1.1.1.54" +sas_workshops_lib_lvbuildspec_for_g_cli = "1.2.1.104" +sas_workshops_lib_vipb_builder_for_g_cli = "1.1.6.46" +wiresmith_technology_lib_g_cli = "3.0.1.98" \ No newline at end of file diff --git a/scripts/refresh-vipm-lock/RefreshVipmLock.ps1 b/scripts/refresh-vipm-lock/RefreshVipmLock.ps1 new file mode 100644 index 00000000..29e820af --- /dev/null +++ b/scripts/refresh-vipm-lock/RefreshVipmLock.ps1 @@ -0,0 +1,134 @@ +<# +.SYNOPSIS + Generates or checks vipm.lock from vipm.toml using the VIPM CLI inside a Linux Docker container. + +.DESCRIPTION + Installs/activates VIPM, runs `vipm refresh` to populate the repository cache for the + target LabVIEW version/bitness, then runs `vipm lock` (or `vipm lock --check`). + See docs.vipm.io/cli/command-reference and docs.vipm.io/vipm-toml/lock-files. + +.PARAMETER WorkingDirectory + Path (relative to the repo root) containing vipm.toml. + +.PARAMETER LabVIEWVersion + LabVIEW version (YYYY) matching the [project] section of vipm.toml. + +.PARAMETER LabVIEWBitness + "32" or "64" bitness matching the [project] section of vipm.toml. + +.PARAMETER CheckOnly + If set, checks an existing vipm.lock or generates the initial lock when absent. + +.PARAMETER VipmSerialNumber + VIPM Pro serial number. Omit to skip activation (Free edition). + +.PARAMETER VipmFullName + Name used for VIPM Pro activation. + +.PARAMETER VipmEmail + Email used for VIPM Pro activation. + +.PARAMETER VipmDebUrl + URL for the VIPM Linux .deb package. + +.PARAMETER DockerImage + Docker image name. + +.PARAMETER ImageTag + Docker image tag. + +.NOTES + Leaf script for the 'refresh-vipm-lock' dispatcher action. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$WorkingDirectory, + + [Parameter(Mandatory = $true)] + [string]$LabVIEWVersion, + + [Parameter(Mandatory = $true)] + [string]$LabVIEWBitness, + + [Parameter(Mandatory = $false)] + [switch]$CheckOnly, + + [Parameter(Mandatory = $false)] + [string]$VipmSerialNumber = "", + + [Parameter(Mandatory = $false)] + [string]$VipmFullName = "", + + [Parameter(Mandatory = $false)] + [string]$VipmEmail = "", + + [Parameter(Mandatory = $false)] + [string]$VipmDebUrl = "https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb", + + [Parameter(Mandatory = $false)] + [string]$DockerImage = "nationalinstruments/labview", + + [Parameter(Mandatory = $false)] + [string]$ImageTag = "latest-linux" +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +try { + $fullImage = "${DockerImage}:${ImageTag}" + Write-Information "Docker Image: $fullImage" -InformationAction Continue + + $scriptDir = $PSScriptRoot + $refreshScript = Join-Path $scriptDir 'refresh-vipm-lock.sh' + if (-not (Test-Path $refreshScript)) { + throw "Helper script not found: $refreshScript" + } + + $containerScriptPath = "/tmp/refresh-vipm-lock.sh" + $checkOnlyValue = if ($CheckOnly) { 'true' } else { 'false' } + + $bashArgs = @( + "--working-directory", "'$WorkingDirectory'" + "--labview-version", "'$LabVIEWVersion'" + "--labview-bitness", "'$LabVIEWBitness'" + "--check-only", "'$checkOnlyValue'" + "--vipm-deb-url", "'$VipmDebUrl'" + ) + $bashCommand = "chmod +x $containerScriptPath && $containerScriptPath $($bashArgs -join ' ')" + + Write-Information "Running vipm refresh + lock in Docker container..." -InformationAction Continue + Write-Verbose "Command: bash -c `"$bashCommand`"" + + docker run --rm ` + -v "${PWD}:/workspace" ` + -v "${refreshScript}:${containerScriptPath}" ` + -w /workspace ` + -e "VIPM_SERIAL_NUMBER=$VipmSerialNumber" ` + -e "VIPM_FULL_NAME=$VipmFullName" ` + -e "VIPM_EMAIL=$VipmEmail" ` + $fullImage ` + bash -c $bashCommand ` + *>&1 | ForEach-Object { Write-Information $_ -InformationAction Continue } + + $exitCode = $LASTEXITCODE + if ($exitCode -ne 0) { + throw "vipm lock generation/check failed with exit code $exitCode" + } + + if (-not $CheckOnly) { + $lockPath = Join-Path $WorkingDirectory 'vipm.lock' + if (-not (Test-Path $lockPath)) { + throw "vipm.lock was not created at $lockPath" + } + } + + Write-Information "vipm.lock refresh succeeded" -InformationAction Continue + exit 0 +} +catch { + Write-Error "RefreshVipmLock failed: $_" + exit 1 +} diff --git a/scripts/refresh-vipm-lock/refresh-vipm-lock.sh b/scripts/refresh-vipm-lock/refresh-vipm-lock.sh new file mode 100644 index 00000000..8e8ee672 --- /dev/null +++ b/scripts/refresh-vipm-lock/refresh-vipm-lock.sh @@ -0,0 +1,98 @@ +#!/usr/bin/env bash +# Installs/activates VIPM, refreshes the repository cache, and generates or +# checks vipm.lock from vipm.toml. Executed inside the VIPM Linux container by +# RefreshVipmLock.ps1. +set -euo pipefail + +WORKING_DIRECTORY="" +LABVIEW_VERSION="" +LABVIEW_BITNESS="" +CHECK_ONLY="false" +VIPM_DEB_URL="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --working-directory) WORKING_DIRECTORY="$2"; shift 2 ;; + --labview-version) LABVIEW_VERSION="$2"; shift 2 ;; + --labview-bitness) LABVIEW_BITNESS="$2"; shift 2 ;; + --check-only) CHECK_ONLY="$2"; shift 2 ;; + --vipm-deb-url) VIPM_DEB_URL="$2"; shift 2 ;; + *) echo "error: unknown argument '$1'" >&2; exit 2 ;; + esac +done + +if [ -z "${VIPM_SERIAL_NUMBER:-}" ] || [ -z "${VIPM_FULL_NAME:-}" ] || [ -z "${VIPM_EMAIL:-}" ]; then + echo "error: VIPM Pro activation requires VIPM_SERIAL_NUMBER, VIPM_FULL_NAME, and VIPM_EMAIL secrets." >&2 + exit 2 +fi + +apt-get update +apt-get install -y wget ca-certificates xvfb + +if ! command -v vipm >/dev/null 2>&1; then + wget -O /tmp/vipm.deb "${VIPM_DEB_URL}" + apt-get install -y /tmp/vipm.deb +fi + +export DISPLAY=:99 +export VIPM_TIMEOUT=500 +Xvfb "$DISPLAY" -screen 0 1280x720x24 -ac +extension GLX +render -noreset >/tmp/xvfb.log 2>&1 & + +vipm --version + +# VIPM writes detailed failures to its error-log dirs, not stdout. +dump_vipm_logs() { + echo "----- VIPM error logs -----" + for d in /usr/local/jki/vipm/VIPM-CLI/error /usr/local/jki/vipm/error; do + [ -d "$d" ] && find "$d" -type f -print -exec cat {} \; 2>/dev/null || true + done + echo "----- end VIPM error logs -----" +} + +echo "VIPM Pro credentials are configured; attempting activation." +if vipm activate --serial-number "$VIPM_SERIAL_NUMBER" --name "$VIPM_FULL_NAME" --email "$VIPM_EMAIL"; then + echo "VIPM Pro activation succeeded." +else + ec=$? + echo "error: VIPM Pro activation failed with exit code $ec" >&2 + dump_vipm_logs + exit "$ec" +fi + +cd "$WORKING_DIRECTORY" + +# Clean runner has no repository cache; populate it for this project's LabVIEW +# target before lock resolution (see docs.vipm.io/cli/command-reference#vipm-refresh). +vipm refresh --labview-version "$LABVIEW_VERSION" --labview-bitness "$LABVIEW_BITNESS" + +if [ "$CHECK_ONLY" = "true" ]; then + if [ ! -f vipm.lock ]; then + echo "vipm.lock does not exist; generating the initial lock file." + if vipm lock; then + echo "Initial vipm.lock generated successfully." + else + ec=$? + echo "error: initial 'vipm lock' generation failed with exit code $ec" >&2 + dump_vipm_logs + exit "$ec" + fi + else + if vipm lock --check; then + : + else + ec=$? + echo "error: 'vipm lock --check' failed with exit code $ec" >&2 + dump_vipm_logs + exit "$ec" + fi + fi +else + if vipm lock; then + : + else + ec=$? + echo "error: 'vipm lock' failed with exit code $ec" >&2 + dump_vipm_logs + exit "$ec" + fi +fi diff --git a/scripts/update-vipm-dependencies/UpdateVipmDependencies.ps1 b/scripts/update-vipm-dependencies/UpdateVipmDependencies.ps1 new file mode 100644 index 00000000..099558f1 --- /dev/null +++ b/scripts/update-vipm-dependencies/UpdateVipmDependencies.ps1 @@ -0,0 +1,120 @@ +<# +.SYNOPSIS + Bumps every dependency in vipm.toml to its latest available version and regenerates vipm.lock. + +.DESCRIPTION + Installs/activates VIPM, runs `vipm refresh`, then runs `vipm add ` (no version + suffix, which resolves to the latest available version per + docs.vipm.io/cli/command-reference#vipm-add) for every package declared in vipm.toml's + [dependencies] table, and finally regenerates vipm.lock with `vipm lock` (the only + command that writes it - see docs.vipm.io/vipm-toml/lock-files). + +.PARAMETER WorkingDirectory + Path (relative to the repo root) containing vipm.toml. + +.PARAMETER LabVIEWVersion + LabVIEW version (YYYY) matching the [project] section of vipm.toml. + +.PARAMETER LabVIEWBitness + "32" or "64" bitness matching the [project] section of vipm.toml. + +.PARAMETER VipmSerialNumber + VIPM Pro serial number. `vipm add` requires Community or Professional edition. + +.PARAMETER VipmFullName + Name used for VIPM Pro activation. + +.PARAMETER VipmEmail + Email used for VIPM Pro activation. + +.PARAMETER VipmDebUrl + URL for the VIPM Linux .deb package. + +.PARAMETER DockerImage + Docker image name. + +.PARAMETER ImageTag + Docker image tag. + +.NOTES + Leaf script for the 'update-vipm-dependencies' dispatcher action. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$WorkingDirectory, + + [Parameter(Mandatory = $true)] + [string]$LabVIEWVersion, + + [Parameter(Mandatory = $true)] + [string]$LabVIEWBitness, + + [Parameter(Mandatory = $false)] + [string]$VipmSerialNumber = "", + + [Parameter(Mandatory = $false)] + [string]$VipmFullName = "", + + [Parameter(Mandatory = $false)] + [string]$VipmEmail = "", + + [Parameter(Mandatory = $false)] + [string]$VipmDebUrl = "https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb", + + [Parameter(Mandatory = $false)] + [string]$DockerImage = "nationalinstruments/labview", + + [Parameter(Mandatory = $false)] + [string]$ImageTag = "latest-linux" +) + +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +try { + $fullImage = "${DockerImage}:${ImageTag}" + Write-Information "Docker Image: $fullImage" -InformationAction Continue + + $scriptDir = $PSScriptRoot + $updateScript = Join-Path $scriptDir 'update-vipm-dependencies.sh' + if (-not (Test-Path $updateScript)) { + throw "Helper script not found: $updateScript" + } + + $containerScriptPath = "/tmp/update-vipm-dependencies.sh" + $bashArgs = @( + "--working-directory", "'$WorkingDirectory'" + "--labview-version", "'$LabVIEWVersion'" + "--labview-bitness", "'$LabVIEWBitness'" + "--vipm-deb-url", "'$VipmDebUrl'" + ) + $bashCommand = "chmod +x $containerScriptPath && $containerScriptPath $($bashArgs -join ' ')" + + Write-Information "Running vipm dependency update in Docker container..." -InformationAction Continue + Write-Verbose "Command: bash -c `"$bashCommand`"" + + docker run --rm ` + -v "${PWD}:/workspace" ` + -v "${updateScript}:${containerScriptPath}" ` + -w /workspace ` + -e "VIPM_SERIAL_NUMBER=$VipmSerialNumber" ` + -e "VIPM_FULL_NAME=$VipmFullName" ` + -e "VIPM_EMAIL=$VipmEmail" ` + $fullImage ` + bash -c $bashCommand ` + *>&1 | ForEach-Object { Write-Information $_ -InformationAction Continue } + + $exitCode = $LASTEXITCODE + if ($exitCode -ne 0) { + throw "vipm dependency update failed with exit code $exitCode" + } + + Write-Information "vipm dependency update succeeded" -InformationAction Continue + exit 0 +} +catch { + Write-Error "UpdateVipmDependencies failed: $_" + exit 1 +} diff --git a/scripts/update-vipm-dependencies/update-vipm-dependencies.sh b/scripts/update-vipm-dependencies/update-vipm-dependencies.sh new file mode 100644 index 00000000..3d4d9087 --- /dev/null +++ b/scripts/update-vipm-dependencies/update-vipm-dependencies.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# Bumps every dependency declared in vipm.toml's [dependencies] table to its +# latest available version (vipm add with no version suffix resolves to +# latest per docs.vipm.io/cli/command-reference#vipm-add), then regenerates +# vipm.lock. Executed inside the VIPM Linux container by +# UpdateVipmDependencies.ps1. +set -euo pipefail + +WORKING_DIRECTORY="" +LABVIEW_VERSION="" +LABVIEW_BITNESS="" +VIPM_DEB_URL="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --working-directory) WORKING_DIRECTORY="$2"; shift 2 ;; + --labview-version) LABVIEW_VERSION="$2"; shift 2 ;; + --labview-bitness) LABVIEW_BITNESS="$2"; shift 2 ;; + --vipm-deb-url) VIPM_DEB_URL="$2"; shift 2 ;; + *) echo "error: unknown argument '$1'" >&2; exit 2 ;; + esac +done + +if [ -z "${VIPM_SERIAL_NUMBER:-}" ] || [ -z "${VIPM_FULL_NAME:-}" ] || [ -z "${VIPM_EMAIL:-}" ]; then + echo "error: VIPM Pro activation requires VIPM_SERIAL_NUMBER, VIPM_FULL_NAME, and VIPM_EMAIL secrets." >&2 + exit 2 +fi + +apt-get update +apt-get install -y wget ca-certificates xvfb + +if ! command -v vipm >/dev/null 2>&1; then + wget -O /tmp/vipm.deb "${VIPM_DEB_URL}" + apt-get install -y /tmp/vipm.deb +fi + +export DISPLAY=:99 +export VIPM_TIMEOUT=500 +Xvfb "$DISPLAY" -screen 0 1280x720x24 -ac +extension GLX +render -noreset >/tmp/xvfb.log 2>&1 & + +vipm --version + +# VIPM writes detailed failures to its error-log dirs, not stdout. +dump_vipm_logs() { + echo "----- VIPM error logs -----" + for d in /usr/local/jki/vipm/VIPM-CLI/error /usr/local/jki/vipm/error; do + [ -d "$d" ] && find "$d" -type f -print -exec cat {} \; 2>/dev/null || true + done + echo "----- end VIPM error logs -----" +} + +echo "VIPM Pro credentials are configured; attempting activation." +if vipm activate --serial-number "$VIPM_SERIAL_NUMBER" --name "$VIPM_FULL_NAME" --email "$VIPM_EMAIL"; then + echo "VIPM Pro activation succeeded." +else + ec=$? + echo "error: VIPM Pro activation failed with exit code $ec" >&2 + dump_vipm_logs + exit "$ec" +fi + +cd "$WORKING_DIRECTORY" + +vipm refresh --labview-version "$LABVIEW_VERSION" --labview-bitness "$LABVIEW_BITNESS" + +# Extract dependency names from the [dependencies] table (stops at the next [section]). +mapfile -t deps < <(awk ' + /^\[dependencies\]/ { in_section=1; next } + /^\[/ { in_section=0 } + in_section && NF { split($0, parts, "="); gsub(/[ \t"]/, "", parts[1]); if (parts[1] != "") print parts[1] } +' vipm.toml) + +echo "Found ${#deps[@]} dependencies to check: ${deps[*]}" + +failed=() +for pkg in "${deps[@]}"; do + echo "::group::vipm add $pkg" + # No version suffix: vipm add resolves and pins the latest available version + # (docs.vipm.io/cli/command-reference#vipm-add, example "Add one or more + # dependencies (latest available version)"). + if vipm add "$pkg" --labview-version "$LABVIEW_VERSION" --labview-bitness "$LABVIEW_BITNESS"; then + : + else + ec=$? + echo "error: could not resolve/update $pkg (exit $ec)" >&2 + dump_vipm_logs + failed+=("$pkg") + fi + echo "::endgroup::" +done + +if [ "${#failed[@]}" -gt 0 ]; then + echo "error: failed to update ${#failed[@]} package(s): ${failed[*]}" >&2 + echo "Not generating vipm.lock or opening a PR with a partial/incomplete update." >&2 + exit 1 +fi + +# vipm add never creates/fully reconciles vipm.lock (docs.vipm.io/vipm-toml/lock-files), +# so regenerate it explicitly - this is the only command that writes the lock. +vipm lock diff --git a/tests/pester/RefreshVipmLock.Workflow.Tests.ps1 b/tests/pester/RefreshVipmLock.Workflow.Tests.ps1 new file mode 100644 index 00000000..5f38c217 --- /dev/null +++ b/tests/pester/RefreshVipmLock.Workflow.Tests.ps1 @@ -0,0 +1,44 @@ +#requires -Version 7.0 +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +Describe 'RefreshVipmLock.Workflow' { + $meta = @{ + requirement = 'REQ-043' + Owner = 'NI' + Evidence = 'tests/pester/RefreshVipmLock.Workflow.Tests.ps1' + } + + BeforeAll { + $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..' '..')).Path + Import-Module (Join-Path $repoRoot 'actions' 'OpenSourceActions.psd1') -Force + } + + It 'validates action.yml exists [REQ-043]' -Tag 'REQ-043' { + $actionPath = Join-Path $repoRoot 'refresh-vipm-lock' 'action.yml' + Test-Path $actionPath | Should -Be $true + } + + It 'validates implementation script exists [REQ-043]' -Tag 'REQ-043' { + $scriptPath = Join-Path $repoRoot 'scripts' 'refresh-vipm-lock' 'RefreshVipmLock.ps1' + Test-Path $scriptPath | Should -Be $true + } + + It 'executes dry-run with only required parameters [REQ-043]' -Tag 'REQ-043' { + $result = & "$repoRoot/actions/Invoke-OSAction.ps1" ` + -ActionName 'refresh-vipm-lock' ` + -ArgsJson '{"WorkingDirectory":"scripts/apply-vipc","LabVIEWVersion":"2021","LabVIEWBitness":"64"}' ` + -DryRun + + $LASTEXITCODE | Should -Be 0 + } + + It 'executes dry-run in check-only mode [REQ-043]' -Tag 'REQ-043' { + $result = & "$repoRoot/actions/Invoke-OSAction.ps1" ` + -ActionName 'refresh-vipm-lock' ` + -ArgsJson '{"WorkingDirectory":"scripts/apply-vipc","LabVIEWVersion":"2021","LabVIEWBitness":"64","CheckOnly":true}' ` + -DryRun + + $LASTEXITCODE | Should -Be 0 + } +} diff --git a/tests/pester/UpdateVipmDependencies.Workflow.Tests.ps1 b/tests/pester/UpdateVipmDependencies.Workflow.Tests.ps1 new file mode 100644 index 00000000..575173d2 --- /dev/null +++ b/tests/pester/UpdateVipmDependencies.Workflow.Tests.ps1 @@ -0,0 +1,35 @@ +#requires -Version 7.0 +Set-StrictMode -Version Latest +$ErrorActionPreference = 'Stop' + +Describe 'UpdateVipmDependencies.Workflow' { + $meta = @{ + requirement = 'REQ-044' + Owner = 'NI' + Evidence = 'tests/pester/UpdateVipmDependencies.Workflow.Tests.ps1' + } + + BeforeAll { + $repoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..' '..')).Path + Import-Module (Join-Path $repoRoot 'actions' 'OpenSourceActions.psd1') -Force + } + + It 'validates action.yml exists [REQ-044]' -Tag 'REQ-044' { + $actionPath = Join-Path $repoRoot 'update-vipm-dependencies' 'action.yml' + Test-Path $actionPath | Should -Be $true + } + + It 'validates implementation script exists [REQ-044]' -Tag 'REQ-044' { + $scriptPath = Join-Path $repoRoot 'scripts' 'update-vipm-dependencies' 'UpdateVipmDependencies.ps1' + Test-Path $scriptPath | Should -Be $true + } + + It 'executes dry-run with only required parameters [REQ-044]' -Tag 'REQ-044' { + $result = & "$repoRoot/actions/Invoke-OSAction.ps1" ` + -ActionName 'update-vipm-dependencies' ` + -ArgsJson '{"WorkingDirectory":"scripts/apply-vipc","LabVIEWVersion":"2021","LabVIEWBitness":"64"}' ` + -DryRun + + $LASTEXITCODE | Should -Be 0 + } +} diff --git a/update-vipm-dependencies/action.yml b/update-vipm-dependencies/action.yml new file mode 100644 index 00000000..6f4fd84f --- /dev/null +++ b/update-vipm-dependencies/action.yml @@ -0,0 +1,68 @@ +name: 'Update VIPM Dependencies' +description: 'Bumps every dependency in vipm.toml to its latest available version and regenerates vipm.lock.' +inputs: + working_directory: + description: 'Path (relative to the caller repo root) containing vipm.toml.' + required: true + labview_version: + description: 'LabVIEW version (YYYY) matching the [project] section of vipm.toml.' + required: true + labview_bitness: + description: '"32" or "64" bitness matching the [project] section of vipm.toml.' + required: true + vipm_serial_number: + description: 'VIPM Pro serial number (pass from a secret in the caller). `vipm add` requires Community or Professional edition.' + required: false + vipm_full_name: + description: 'Name used for VIPM Pro activation.' + required: false + vipm_email: + description: 'Email used for VIPM Pro activation.' + required: false + vipm_deb_url: + description: 'Override URL for the VIPM Linux .deb package.' + default: 'https://traffic.libsyn.com/secure/jkinc/vipm_26.3.1-4025_amd64.deb' + required: false + docker_image: + description: 'Docker image name.' + default: 'nationalinstruments/labview' + required: false + image_tag: + description: 'Docker image tag.' + default: 'latest-linux' + 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 update-vipm-dependencies + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + $args = @{ + WorkingDirectory = '${{ inputs.working_directory }}' + LabVIEWVersion = '${{ inputs.labview_version }}' + LabVIEWBitness = '${{ inputs.labview_bitness }}' + VipmSerialNumber = '${{ inputs.vipm_serial_number }}' + VipmFullName = '${{ inputs.vipm_full_name }}' + VipmEmail = '${{ inputs.vipm_email }}' + VipmDebUrl = '${{ inputs.vipm_deb_url }}' + DockerImage = '${{ inputs.docker_image }}' + ImageTag = '${{ inputs.image_tag }}' + } + $params = @{ + ActionName = 'update-vipm-dependencies' + Args = $args + LogLevel = '${{ inputs.log_level }}' + } + if ('${{ inputs.dry_run }}' -eq 'true') { $params['DryRun'] = $true } + $script = Join-Path $env:GITHUB_ACTION_PATH '..' 'actions' 'common-dispatch.ps1' + & $script @params + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }