Skip to content

CLI Tests

CLI Tests #64

Workflow file for this run

name: CLI Tests
on:
workflow_call:
inputs:
snap-channel:
type: string
description: "Snap channel to install Multipass from"
required: false
default: "<undefined>"
macos-pkg-url:
type: string
description: "URL to macOS package to install Multipass from"
required: false
default: "<undefined>"
windows-pkg-url:
type: string
description: "URL to Windows package to install Multipass from"
required: false
default: "<undefined>"
pytest-extra-args:
type: string
description: "Extra arguments to be passed to the pytest invocation"
default: ""
workflow_dispatch:
inputs:
snap-channel:
type: string
description: "Snap channel to install Multipass from"
required: false
default: "<undefined>"
macos-pkg-url:
type: string
description: "URL to macOS package to install Multipass from"
required: false
default: "<undefined>"
windows-pkg-url:
type: string
description: "URL to Windows package to install Multipass from"
required: false
default: "<undefined>"
pytest-extra-args:
type: string
description: "Extra arguments to be passed to the pytest invocation"
default: ""
permissions:
contents: read
actions: read
checks: write
env:
SNAP_CHANNEL: ${{ inputs['snap-channel'] }}
MACOS_PKG_URL: ${{ inputs['macos-pkg-url'] }}
WINDOWS_PKG_URL: ${{ inputs['windows-pkg-url'] }}
PYTEST_EXTRA_ARGS: ${{ inputs['pytest-extra-args'] }}
concurrency:
group: cli-tests-${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
determine-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.neo.outputs.matrix }}
has_targets: ${{ steps.neo.outputs.has_targets }}
steps:
- id: neo
uses: actions/github-script@v7
with:
script: |
const {SNAP_CHANNEL, MACOS_PKG_URL, WINDOWS_PKG_URL, PYTEST_EXTRA_ARGS} = process.env
const matrix = { include: [] };
if (SNAP_CHANNEL !== '<undefined>') {
matrix.include.push({
os: 'ubuntu-latest',
label: 'Snap',
'daemon-controller': 'snap',
'sudo-cmd': 'sudo',
'pkg-url': '',
'cmd-prologue': '',
'snap-channel': SNAP_CHANNEL
});
}
if (MACOS_PKG_URL !== '<undefined>') {
matrix.include.push({
os: 'macos-13',
label: 'macOS',
'daemon-controller': 'launchd',
'sudo-cmd': 'sudo',
'pkg-url': MACOS_PKG_URL,
'pkg-download-destination': '$RUNNER_TEMP/multipass.pkg',
'cmd-prologue': 'arch -arch x86_64'
});
}
if (WINDOWS_PKG_URL !== '<undefined>') {
matrix.include.push({
os: 'windows-latest',
label: 'Windows',
'daemon-controller': 'winsvc',
'sudo-cmd': 'gsudo',
'pkg-url': WINDOWS_PKG_URL,
'pkg-download-destination': '$env:RUNNER_TEMP\\multipass.msi',
'cmd-prologue': ''
});
}
core.setOutput('matrix', JSON.stringify(matrix));
core.setOutput('has_targets', String(matrix.include.length > 0));
run-cli-tests:
name: CLI Tests (${{ matrix.label }})
needs: determine-matrix
runs-on: ${{ matrix.os }}
if: ${{ needs.determine-matrix.outputs.has_targets == 'true' }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.determine-matrix.outputs.matrix) }}
steps:
- name: Check out cli-tests
uses: actions/checkout@v5
with:
fetch-depth: 1
submodules: false
sparse-checkout: |
tools/cli_tests
- name: Download package with cURL
if: ${{ matrix['pkg-url'] != '' }}
run: curl -fL "${{ matrix['pkg-url'] }}" -o ${{ matrix['pkg-download-destination'] }}
##################################################################
# Platform-specific
##################################################################
- name: Install prerequisites (Windows)
if: runner.os == 'Windows'
run: |
choco install gsudo -y
echo 'C:\ProgramData\chocolatey\bin' >> "$GITHUB_PATH"
& "C:\tools\gsudo\Current\gsudo.exe" -v
echo "C:\tools\gsudo\Current" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Check snap channel (Linux)
if: runner.os == 'Linux'
run: |
if [ -z "${{ matrix['snap-channel'] }}" ]; then
echo "❌ snap-channel is empty"
exit 1
fi
- name: Install package (Snap)
if: runner.os == 'Linux'
run: ${{ matrix.cmd-prologue }}${{ matrix.sudo-cmd }} snap install multipass --channel=${{ matrix['snap-channel'] }}
- name: Install package (macOS)
if: runner.os == 'macOS'
run: ${{ matrix.cmd-prologue }} ${{ matrix.sudo-cmd }} installer -pkg ${{ matrix['pkg-download-destination'] }} -target /
- name: Install package (Windows)
if: runner.os == 'Windows'
run: |
$msi = "${{ matrix['pkg-download-destination'] }}"
$log = Join-Path $env:RUNNER_TEMP 'multipass-install.log'
Write-Host "Expanded: $msi"
$args = @(
'/i', $msi,
'/qn', '/norestart',
'/l*vx!', $log,
'ADDLOCAL=ALL',
'ALLUSERS=1'
)
$proc = Start-Process -FilePath msiexec.exe -ArgumentList $args -Wait -PassThru
$code = $proc.ExitCode
Write-Host "msiexec exit code: $code"
if (Test-Path $log) {
Get-Content -Path $log -Tail 200
} else {
Write-Warning "Log not found at: $log"
}
if ($code -ne 0) {
throw "MSI install failed with exit code $code"
}
"$env:ProgramFiles\Multipass\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
##################################################################
# Platform-agnostic
##################################################################
- name: Install cli-tests dependencies
id: install-cli-test-deps
run: ${{ matrix.cmd-prologue }} ${{ matrix.sudo-cmd }} pip install -e ./tools/cli_tests/ --break-system-packages
- name: Run cli-tests
id: run-cli-tests
run: ${{ matrix.cmd-prologue }} pytest -s tools/cli_tests --daemon-controller=${{ matrix.daemon-controller }} --junitxml=reports/junit.xml ${{ env.pytest-extra-args }}
- name: Report cli-tests results to Github Checks
if: success() || failure()
uses: dorny/test-reporter@v2
with:
name: CLI Test results (${{ matrix.label }})
path: reports/junit.xml
reporter: java-junit # understands standard JUnit
fail-on-error: true # fail job if there are test failures