Skip to content

Assign/remove database-client role during evacuation/restore #23439

Assign/remove database-client role during evacuation/restore

Assign/remove database-client role during evacuation/restore #23439

Workflow file for this run

name: Tests
on:
push:
branches:
- main
- stable-*
pull_request:
workflow_dispatch:
inputs:
static-analysis:
description: Whether to run `make static-analysis`
required: true
type: boolean
default: true
unit-tests:
description: Whether to run `make check-unit`
required: true
type: boolean
default: true
coverage:
description: Whether to enable Go coverage collection
required: true
type: boolean
default: false
ubuntu-releases:
description: Ubuntu releases to run the tests against. In JSON format, i.e. '["22.04", "24.04"]'.
type: choice
default: '["24.04"]'
options:
- '["22.04", "24.04"]'
- '["22.04"]'
- '["24.04"]'
snap-risk:
description: Snap risk level, `edge`, `candidate` or `stable`
type: choice
default: 'edge'
options:
- 'edge'
- 'candidate'
- 'stable'
tmate-debug:
description: Use tmate debugging session on integration test failure.
type: boolean
default: false
schedule:
- cron: '0 0 * * *' # Test TICS daily
env:
LXD_REQUIRED_TESTS: "storage_buckets,network_ovn"
GOCOVERAGE: ${{ (( github.event_name == 'workflow_dispatch' && github.event.inputs.coverage == 'true' ) || ( github.event_name == 'schedule' && github.repository == 'canonical/lxd' )) && 'true' || 'false' }}
GOCOVERDIR: '' # Later set to the fully qualified path if needed
IMAGE_CACHE_DIR: "/home/runner/image-cache"
SNAP_CACHE_DIR: "/home/runner/snap-cache"
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
defaults:
run:
# Make sure bash is always invoked with `-eo pipefail`
# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
shell: bash
jobs:
code-tests:
env:
CGO_CFLAGS: "-I/home/runner/go/bin/dqlite/include/ -I/home/runner/go/bin/liblxc/include/"
CGO_LDFLAGS: "-L/home/runner/go/bin/dqlite/libs/"
LD_LIBRARY_PATH: "/home/runner/go/bin/dqlite/libs/"
LD_RUN_PATH: "/home/runner/go/bin/dqlite/libs/"
CGO_LDFLAGS_ALLOW: "(-Wl,-wrap,pthread_create)|(-Wl,-z,now)"
if: ${{ github.event_name != 'schedule' || github.repository == 'canonical/lxd' }}
name: Code
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
# A non-shallow clone is needed for the Differential ShellCheck
fetch-depth: 0
persist-credentials: false
- name: Require GHA pinning
uses: ./.github/actions/require-gha-pinning
- name: Tune disk performance
uses: ./.github/actions/tune-disk-performance
- name: Dependency Review
uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2
if: github.event_name == 'pull_request'
# XXX: `make static-analysis` also run shellcheck but this one provides
# useful feedback in the PR through github-code-scanning bot
- id: ShellCheck
name: Differential ShellCheck
uses: redhat-plumbers-in-action/differential-shellcheck@0d9e5b29625f871e6a4215380486d6f1a7cb6cdd # v5.5.5
with:
token: ${{ secrets.GITHUB_TOKEN }}
strict-check-on-push: true
if: github.event_name == 'pull_request'
- name: Upload artifact with ShellCheck defects in SARIF format
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: Differential ShellCheck SARIF
path: ${{ steps.ShellCheck.outputs.sarif }}
retention-days: 1
if: ${{ github.event_name == 'pull_request' && runner.debug == '1' && !cancelled() }}
- name: Install Go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version-file: 'go.mod'
- name: Install Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
if: github.event_name != 'pull_request'
with:
cache: 'pip' # caching pip dependencies
cache-dependency-path: |
doc/.sphinx/build_requirements.py
doc/.sphinx/requirements.txt
doc/custom_conf.py
python-version: '3.x' # satisfied by any 3.x version already installed
- name: Install build dependencies
uses: ./.github/actions/install-lxd-builddeps
- name: Download go dependencies
run: |
set -eux
sudo chmod o+w {go.mod,go.sum}
go mod download
# Check compatibility with min Go version
make check-gomin
- name: Make GOCOVERDIR
run: |
set -eux
mkdir -p coverage
cd coverage
echo "GOCOVERDIR=$(pwd)" >> "${GITHUB_ENV}"
if: env.GOCOVERAGE == 'true'
- name: Make LXD tarball and unpack it
env:
CUSTOM_VERSION: "test"
run: |
set -eux
make dist
tar -xzf lxd-test.tar.gz -C /home/runner/work/lxd/
rm lxd-test.tar.gz
# In code-tests, this action warms the cache for the system-tests job
- name: Build or restore dqlite/liblxc dependencies
uses: ./.github/actions/cache-dqlite-liblxc
- name: Update env variables for deps
run: |
set -eux
LIBLXC_ARCH_LIBS="$(readlink -e /home/runner/go/bin/liblxc/libs/*-linux-gnu)"
echo "CGO_LDFLAGS=${CGO_LDFLAGS} -L${LIBLXC_ARCH_LIBS}" >> "${GITHUB_ENV}"
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${LIBLXC_ARCH_LIBS}" >> "${GITHUB_ENV}"
echo "LD_RUN_PATH=${LD_RUN_PATH}:${LIBLXC_ARCH_LIBS}" >> "${GITHUB_ENV}"
echo "PKG_CONFIG_PATH=${LIBLXC_ARCH_LIBS}/pkgconfig" >> "${GITHUB_ENV}"
- name: Build binaries
run: |
set -eux
# Build from unpacked dist tarball.
cd /home/runner/work/lxd/lxd-test
make
- name: Check lxc/lxd-agent binary sizes
if: env.GOCOVERAGE != 'true'
run: |
set -eux
# bin/max (sizes are in MiB)
SIZES="lxc 17
lxd-agent 14"
MIB="$((1024 * 1024))"
# Strip a copy of the freshly built binaries and check their size
mkdir /tmp/bin
while read -r bin max; do
install --strip "/home/runner/go/bin/${bin}" /tmp/bin/
cur="$(stat --format=%s "/tmp/bin/${bin}")"
min=$((max - 1))
min_mib="$((min * MIB))"
max_mib="$((max * MIB))"
rm -f "/tmp/bin/${bin}"
if [ "${cur}" -gt "${max_mib}" ]; then
echo "FAIL: ${bin} binary size exceeds ${max}MiB"
exit 1
fi
# XXX: check for when we need to lower the min/max sizes
if [ "${cur}" -lt "${min_mib}" ]; then
echo "Congratulations: ${bin} binary size reduced below ${min}MiB"
echo "It is now time to edit the workflow job to use smaller min/max sizes for ${bin}"
exit 1
fi
echo "OK: ${bin} is between ${min} and ${max}MiB"
done <<< ${SIZES}
- name: Check binaries were compiled with the Go minimum version
run: |
set -eux
# Check which Go version was used to compile each of the lxc/lxd binaries
GOMIN="$(sed -n 's/^GOMIN=\([0-9.]\+\)$/\1/p' Makefile)"
UNEXPECTED_GO_VER="$(go version -v ~/go/bin/lxc* ~/go/bin/lxd* | grep -vF ": go${GOMIN}" || true)"
if [ -n "${UNEXPECTED_GO_VER:-}" ]; then
echo "Some binaries were compiled with an unexpected Go version (!= ${GOMIN}):"
echo "${UNEXPECTED_GO_VER}"
exit 1
fi
# XXX: `make static-analysis` also run golangci-lint but this one provides
# useful feedback in the PR through github-code-scanning bot
- name: Run golangci-lint
if: github.event_name == 'pull_request' || github.event_name == 'schedule'
uses: golangci/golangci-lint-action@e7fa5ac41e1cf5b7d48e45e42232ce7ada589601 # v8
- name: Run static analysis
if: ${{ github.event_name != 'workflow_dispatch' || inputs.static-analysis == 'true' }}
run: |
set -eux
sudo chmod o+w ./lxd/metadata/configuration.json
sudo chmod o+w ./doc/metadata.txt
sudo chmod o+w ./po/*
sudo chmod o+w ./lxd/auth/entitlements_generated.go
sudo chmod o+w ./lxd/auth/drivers/openfga_model.openfga
make static-analysis
- name: Unit tests
if: ${{ github.event_name != 'workflow_dispatch' || inputs.unit-tests == 'true' }}
run: |
set -eux
chmod +x ~
echo "root:1000000:1000000000" | sudo tee /etc/subuid /etc/subgid
sudo --preserve-env=CGO_CFLAGS,CGO_LDFLAGS,CGO_LDFLAGS_ALLOW,GOCOVERDIR,PKG_CONFIG_PATH,LD_LIBRARY_PATH LD_LIBRARY_PATH=${LD_LIBRARY_PATH} env "PATH=${PATH}" make check-unit
- name: Upload coverage data
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: coverage-unit
path: ${{env.GOCOVERDIR}}
retention-days: 1
if: env.GOCOVERDIR != ''
- name: Prime cache with external test images
uses: ./.github/actions/download-images
with:
prime-cache-only: true
image-cache-dir: ${{ env.IMAGE_CACHE_DIR }}
- name: Prime cache with snap dependencies
uses: ./.github/actions/download-snaps
with:
prime-cache-only: true
snap-cache-dir: ${{ env.SNAP_CACHE_DIR }}
- name: Prime cache with minio/mc
uses: ./.github/actions/download-minio
with:
prime-cache-only: true
- name: Prime cache with virtiofsd
uses: ./.github/actions/download-virtiofsd
with:
prime-cache-only: true
- name: Upload system test dependencies
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: system-test-deps
path: |
/home/runner/go/bin/lxc*
/home/runner/go/bin/lxd*
/home/runner/go/bin/devlxd-client
/home/runner/go/bin/fuidshift
/home/runner/go/bin/mini-oidc
/home/runner/go/bin/sysinfo
retention-days: 1
system-tests:
env:
LXD_CEPH_CLUSTER: "ceph"
LXD_CEPH_CEPHFS: "cephfs"
LXD_CEPH_CEPHOBJECT_RADOSGW: "http://127.0.0.1"
LXD_OVN_NB_CONNECTION: "ssl:127.0.0.1:6641"
LXD_OVN_NB_CLIENT_CRT_FILE: "/var/snap/microovn/common/data/pki/client-cert.pem"
LXD_OVN_NB_CLIENT_KEY_FILE: "/var/snap/microovn/common/data/pki/client-privkey.pem"
LXD_OVN_NB_CA_CRT_FILE: "/var/snap/microovn/common/data/pki/cacert.pem"
LXD_VERBOSE: "1"
LXD_OFFLINE: "1"
LXD_TMPFS: "1"
GOTRACEBACK: "crash"
if: ${{ github.event_name != 'schedule' || github.repository == 'canonical/lxd' }}
name: System
runs-on: ubuntu-24.04
needs: code-tests
strategy:
fail-fast: false
matrix:
suite: ["cluster", "standalone", "snap"]
backend: ["dir", "btrfs", "lvm", "zfs", "ceph", "random"]
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Tune disk performance
uses: ./.github/actions/tune-disk-performance
- name: Reclaim some memory
uses: ./.github/actions/reclaim-memory
- name: Remove docker
uses: ./.github/actions/disable-docker
- name: Install Go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version-file: 'go.mod'
- name: Install runtime dependencies
uses: ./.github/actions/install-lxd-runtimedeps
# Restore the cache warmed in code-tests job
- name: Build or restore dqlite/liblxc dependencies
uses: ./.github/actions/cache-dqlite-liblxc
# Restore the cache warmed in code-tests job
- name: Download external test images
uses: ./.github/actions/download-images
with:
image-cache-dir: ${{ env.IMAGE_CACHE_DIR }}
# Restore the cache warmed in code-tests job
- name: Download snap dependencies
uses: ./.github/actions/download-snaps
with:
snap-cache-dir: ${{ env.SNAP_CACHE_DIR }}
# Restore the cache warmed in code-tests job
- name: Download minio/mc
uses: ./.github/actions/download-minio
# Restore the cache warmed in code-tests job
- name: Download virtiofsd
uses: ./.github/actions/download-virtiofsd
- name: Download system test dependencies
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: system-test-deps
merge-multiple: true
path: /home/runner/go/bin
- name: Set exec perms on LXD binaries
run: |
set -eux
ls -lR /home/runner/go/bin/
chmod uog+x /home/runner/go/bin/*
- name: Setup MicroCeph
if: ${{ matrix.backend == 'ceph' }}
uses: ./.github/actions/setup-microceph
with:
osd-count: 3
snap-cache-dir: ${{ env.SNAP_CACHE_DIR }}
- name: Setup MicroOVN
uses: ./.github/actions/setup-microovn
with:
snap-cache-dir: ${{ env.SNAP_CACHE_DIR }}
- name: Make GOCOVERDIR
run: |
set -eux
mkdir -p coverage
cd coverage
echo "GOCOVERDIR=$(pwd)" >> "${GITHUB_ENV}"
if: env.GOCOVERAGE == 'true'
- name: Sanitize Artifact Name
id: sanitize
env:
ID: ${{ matrix.suite }}-${{ matrix.backend }}
run: |
set -eux
echo "artifact_name=$(echo "${ID}" | tr ': /' '-_-')" >> "${GITHUB_OUTPUT}"
- name: "Run system tests (${{ matrix.suite }}, ${{ matrix.backend }})"
run: |
set -eux
chmod +x ~
echo "root:1000000:1000000000" | sudo tee /etc/subuid /etc/subgid
cd test
export PATH="$PATH:/snap/microovn/current/commands"
# Check if there are existing coredumps
if [ -n "$(ls -A /var/crash/)" ]; then
echo "WARNING: coredumps found before running the system tests, removing them"
sudo rm /var/crash/*
fi
sudo --preserve-env=PATH,GOPATH,GOCOVERDIR,GITHUB_ACTIONS,GITHUB_STEP_SUMMARY,LXD_VERBOSE,LXD_REPEAT_TESTS,LXD_BACKEND,LXD_CEPH_CLUSTER,LXD_CEPH_CEPHFS,LXD_CEPH_CEPHOBJECT_RADOSGW,LXD_OVN_NB_CONNECTION,LXD_OVN_NB_CLIENT_CRT_FILE,LXD_OVN_NB_CLIENT_KEY_FILE,LXD_OVN_NB_CA_CRT_FILE,LXD_OFFLINE,LXD_SKIP_TESTS,LXD_REQUIRED_TESTS,GOTRACEBACK,LXD_TMPFS LXD_BACKEND=${{ matrix.backend }} ./main.sh ${{ matrix.suite }}
- name: Upload crash dumps
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: crash-dumps-${{ steps.sanitize.outputs.artifact_name }}
path: |
/var/crash/core-*
retention-days: 5
if-no-files-found: ignore
- name: Upload coverage data
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: coverage-${{ steps.sanitize.outputs.artifact_name }}
path: ${{ env.GOCOVERDIR }}
retention-days: 1
if: env.GOCOVERDIR != ''
- name: Tmate debugging session
if: ${{ failure() && inputs.tmate-debug }}
timeout-minutes: 30
uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23
with:
# Never allow public SSH access
limit-access-to-actor: true
snap-tests:
if: github.event_name != 'schedule' || github.repository == 'canonical/lxd'
needs: code-tests
env:
BRANCH_NAME: ${{ github.ref_name }}
SNAP_RISK: ${{ inputs.snap-risk || 'edge' }}
SNAP_TRACK: "latest"
name: Snap (${{ matrix.test }} - ${{ matrix.os }})
runs-on: ubuntu-${{ matrix.os }}
# avoid runaway test burning 6 hours of CI
timeout-minutes: 60
permissions:
# need that to manipulate caches
actions: write
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON(inputs.ubuntu-releases || '["24.04"]') }}
test:
- cgroup
- cloud-init
- cluster
- container
- container-copy
- container-nesting
- conversion
- cpu-vm
- devlxd-container
- devlxd-vm
- docker
- efi-vars-editor-vm
- lxd-installer
- lxd-user
- interception
- network-bridge-firewall
- network-ovn ovn:deb
- network-ovn ovn:latest/edge
- network-routed
# XXX: Skip pylxd tests until https://github.com/canonical/pylxd/pull/677 is merged.
#- pylxd
- qemu-external-vm
- snapd
- storage-buckets
- storage-disks-vm
- storage-metadata
- storage-vm btrfs
- storage-vm ceph
- storage-vm dir
- storage-vm lvm
- storage-vm lvm-thin
- storage-vm zfs
- storage-volumes-vm
- tpm-vm
# Skip UI tests as they are unreliable and similar ones are done
# against the non-snap daemon
#- ui chromium
#- ui firefox
- vm
- vm-migration
- vm-nesting
exclude:
# some tests are not worth testing on specific OSes
- os: 22.04
test: lxd-installer
- os: 22.04
test: qemu-external-vm
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Tune disk performance
uses: ./.github/actions/tune-disk-performance
- name: Checkout lxd-ci
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
repository: 'canonical/lxd-ci'
ref: main
path: lxd-ci
persist-credentials: false
- name: Reclaim some memory
uses: ./.github/actions/reclaim-memory
- name: Reclaim disk space
# This can take multiple minutes if the runner is busy/slow so only run it when/where absolutely needed.
# Storage tests need it except when using ceph as it uses the ephemeral disk.
if: ${{ matrix.test == 'conversion' || matrix.test == 'vm-nesting' || (startsWith(matrix.test, 'storage-') && !contains(matrix.test, ' ceph')) }}
uses: ./.github/actions/reclaim-disk-space
- name: Remove docker
uses: ./.github/actions/disable-docker
- name: "Disable br_netfilter"
run: |
set -eux
# XXX: br_netfilter causes subtle issues by subjecting internal
# bridge traffic to NAT/MASQUERADING and IP filtering. This
# modules is not normally loaded on stock Ubuntu installs but it
# is on GHA runners.
if lsmod | grep -qw ^br_netfilter; then
sudo modprobe -r br_netfilter
fi
# Restore the cache warmed in code-tests job
- name: Build or restore dqlite/liblxc dependencies
uses: ./.github/actions/cache-dqlite-liblxc
# Restore the cache warmed in code-tests job
- name: Download external test images
uses: ./.github/actions/download-images
with:
image-cache-dir: ${{ env.IMAGE_CACHE_DIR }}
# Restore the cache warmed in code-tests job
- name: Download snap dependencies
uses: ./.github/actions/download-snaps
with:
snap-cache-dir: ${{ env.SNAP_CACHE_DIR }}
# Restore the cache warmed in code-tests job
- name: Download minio/mc
uses: ./.github/actions/download-minio
- name: Download system test dependencies
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: system-test-deps
merge-multiple: true
path: /home/runner/go/bin
- name: Set exec perms on LXD binaries
run: |
set -eux
ls -lR /home/runner/go/bin/
chmod uog+x /home/runner/go/bin/*
- name: Get Date
id: get-date
if: ${{ matrix.test == 'qemu-external-vm' }}
run: |
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
shell: bash
# for simplicity, just use one cache directory
# and make it valid for one day
- uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
id: cache-restore
if: ${{ matrix.test == 'qemu-external-vm' }}
with:
path: /home/runner/work/cache
key: cache-${{ steps.get-date.outputs.date }}
- name: Setup MicroCeph
if: ${{ matrix.test == 'conversion' || matrix.test == 'storage-buckets' || matrix.test == 'storage-vm ceph' || matrix.test == 'storage-volumes-vm' }}
uses: ./.github/actions/setup-microceph
with:
osd-count: 3
snap-cache-dir: ${{ env.SNAP_CACHE_DIR }}
- name: Setup MicroOVN
uses: ./.github/actions/setup-microovn
with:
snap-cache-dir: ${{ env.SNAP_CACHE_DIR }}
- name: Make GOCOVERDIR
run: |
set -eux
mkdir -p coverage
cd coverage
echo "GOCOVERDIR=$(pwd)" >> "${GITHUB_ENV}"
if: env.GOCOVERAGE == 'true'
- name: Sanitize Artifact Name
id: sanitize
env:
ID: ${{ matrix.test }}-${{ matrix.os }}
run: |
set -eux
echo "artifact_name=$(echo "${ID}" | tr ': /' '-_-')" >> "${GITHUB_OUTPUT}"
- name: Snap track selection
run: |
set -eux
if [[ "${BRANCH_NAME}" =~ ^stable- ]]; then
SNAP_TRACK="${BRANCH_NAME#stable-}"
echo "SNAP_TRACK=${SNAP_TRACK}" >> "${GITHUB_ENV}"
fi
- name: Adapt lxd-ci test for sideloading and coverage collection
working-directory: './lxd-ci'
run: |
set -eux
# Avoid lxd-installer getting in the way
sudo rm -f /usr/sbin/lxd /usr/sbin/lxc
cat << EOF > /tmp/install_lxd.sh
# install_lxd replacement that sideloads the built snap and enables coverage collection
install_lxd() (
# Ensure our custom binaries are found first
export PATH="/home/runner/go/bin:${PATH}"
sideload_lxd_snap "${SNAP_TRACK}/${SNAP_RISK}"
gocoverage_lxd_snap
)
EOF
# Add snap helpers from the main repo
sed -i '1 r ../test/includes/snap.sh' bin/helpers
# Replace the install_lxd helper
sed -i '/^# install_lxd:/,/^)$/d' bin/helpers
cat /tmp/install_lxd.sh >> bin/helpers
rm -f /tmp/install_lxd.sh
cat bin/helpers
- name: ${{ matrix.test }}
working-directory: './lxd-ci'
run: |
set -eux
# XXX: prevent accidental usage of `images:` in CI test jobs.
# All tests should be done using officially supported images.
echo '127.0.0.1 images.lxd.canonical.com' | sudo tee /etc/hosts
TEST_SCRIPT="$(echo ${{ matrix.test }} | cut -d " " -f 1)"
EXTRA_ARGS="$(echo ${{ matrix.test }} | cut -d " " -f 2- --only-delimited)"
if [ "${TEST_SCRIPT}" = "cluster" ]; then
dst_track="${SNAP_TRACK}/${SNAP_RISK}"
src_track="${SNAP_TRACK}/stable"
EXTRA_ARGS="${EXTRA_ARGS:-3} ${src_track} ${dst_track}"
elif [ "${TEST_SCRIPT}" = "network-ovn" ]; then
if [ -n "${EXTRA_ARGS}" ]; then
# Strip the `ovn:` prefix
export OVN_SOURCE="${EXTRA_ARGS##ovn:}"
EXTRA_ARGS=""
fi
fi
sudo --preserve-env=GOCOVERDIR,GITHUB_ACTIONS,GITHUB_STEP_SUMMARY,OVN_SOURCE ./bin/local-run "tests/${TEST_SCRIPT}" "${SNAP_TRACK}/${SNAP_RISK}" ${EXTRA_ARGS:-}
# always update cache as we have our own logic of
# cache invalidation and updates in addition to a date check
- name: Delete previous cache
if: ${{ steps.cache-restore.outputs.cache-hit }}
continue-on-error: true
run: |
gh cache delete "cache-${{ steps.get-date.outputs.date }}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
if: ${{ matrix.test == 'qemu-external-vm' }}
with:
path: /home/runner/work/cache
key: cache-${{ steps.get-date.outputs.date }}
- name: Upload ${{ matrix.test }} test reports
if: ${{ always() && startsWith(matrix.test, 'ui ') }}
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: test-report-${{ matrix.test }}-lxd-${{ env.SNAP_TRACK }}-${{ env.SNAP_RISK }}-os-${{ matrix.os }}
path: lxd-ui/test-results
retention-days: 1
- name: Upload crash dumps
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: crash-dumps-${{ steps.sanitize.outputs.artifact_name }}
path: |
/var/crash/core-*
retention-days: 5
if-no-files-found: ignore
- name: Upload coverage data
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: coverage-${{ steps.sanitize.outputs.artifact_name }}
path: ${{ env.GOCOVERDIR }}
retention-days: 1
if: env.GOCOVERDIR != ''
- name: Tmate debugging session
if: ${{ failure() && inputs.tmate-debug }}
timeout-minutes: 30
uses: mxschmitt/action-tmate@c0afd6f790e3a5564914980036ebf83216678101 # v3.23
with:
# Never allow public SSH access
limit-access-to-actor: true
tics:
name: Tiobe TICS
runs-on: ubuntu-24.04
needs: [client, system-tests, snap-tests, ui-e2e-tests]
env:
CGO_CFLAGS: "-I/home/runner/go/bin/dqlite/include/ -I/home/runner/go/bin/liblxc/include/"
CGO_LDFLAGS: "-L/home/runner/go/bin/dqlite/libs/"
LD_LIBRARY_PATH: "/home/runner/go/bin/dqlite/libs/"
LD_RUN_PATH: "/home/runner/go/bin/dqlite/libs/"
CGO_LDFLAGS_ALLOW: "(-Wl,-wrap,pthread_create)|(-Wl,-z,now)"
GOTOOLCHAIN: "local"
if: ${{ ( github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' ) && github.ref_name == 'main' && github.repository == 'canonical/lxd' }}
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Tune disk performance
uses: ./.github/actions/tune-disk-performance
- name: Reclaim some memory
uses: ./.github/actions/reclaim-memory
- name: Remove docker
uses: ./.github/actions/disable-docker
- name: Install Go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version-file: 'go.mod'
- name: Make GOCOVERDIR
run: |
set -eux
mkdir -p coverage
cd coverage
echo "GOCOVERDIR=$(pwd)" >> "${GITHUB_ENV}"
if: env.GOCOVERAGE == 'true'
- name: Download coverage data
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
pattern: coverage-*
path: ${{env.GOCOVERDIR}}
merge-multiple: true
# Restore the cache warmed in code-tests job
- name: Build or restore dqlite/liblxc dependencies
uses: ./.github/actions/cache-dqlite-liblxc
- name: Download system test dependencies
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: system-test-deps
merge-multiple: true
path: /home/runner/go/bin
- name: Prepare for running LXD daemon
run: |
set -eux
# Update env variables for liblxc
LIBLXC_ARCH_LIBS="$(readlink -e /home/runner/go/bin/liblxc/libs/*-linux-gnu)"
echo "CGO_LDFLAGS=${CGO_LDFLAGS} -L${LIBLXC_ARCH_LIBS}" >> "${GITHUB_ENV}"
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${LIBLXC_ARCH_LIBS}" >> "${GITHUB_ENV}"
echo "LD_RUN_PATH=${LD_RUN_PATH}:${LIBLXC_ARCH_LIBS}" >> "${GITHUB_ENV}"
echo "PKG_CONFIG_PATH=${LIBLXC_ARCH_LIBS}/pkgconfig" >> "${GITHUB_ENV}"
- name: Install build dependencies
uses: ./.github/actions/install-lxd-builddeps
- name: Install dependencies
run: |
set -eux
go install github.com/afunix/gocov/gocov@latest
go install github.com/b-dean/[email protected] # XXX: Using this repo is a temporary workaround until https://github.com/AlekSi/gocov-xml/pull/20 is merged. See https://github.com/AlekSi/gocov-xml/pull/20#issuecomment-3275134132 for more details.
go install honnef.co/go/tools/cmd/staticcheck@latest
- name: Convert coverage files
run: |
set -eux
go tool covdata percent -i="${GOCOVERDIR}"
go tool covdata textfmt -i="${GOCOVERDIR}" -o "${GOCOVERDIR}"/coverage.out
head "${GOCOVERDIR}"/coverage.out
# Convert to Cobertura XML format.
gocov convert "${GOCOVERDIR}"/coverage.out > "${GOCOVERDIR}"/coverage.json
gocov-xml < "${GOCOVERDIR}"/coverage.json > "${GOCOVERDIR}"/coverage-go.xml
- name: Run TICS
uses: tiobe/tics-github-action@768de18bedf164ee461bc9ef5e2f2fa1a20b122a # v3.7.0
with:
mode: qserver
project: LXD
viewerUrl: https://canonical.tiobe.com/tiobeweb/TICS/api/cfg?name=GoProjects
branchdir: ${{ github.workspace }}
ticsAuthToken: ${{ secrets.TICSAUTHTOKEN }}
installTics: true
calc: ALL
tmpdir: /tmp/tics
client:
name: Client
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
runs-on: ${{ matrix.os }}
needs: code-tests
steps:
- name: Checkout code
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Install Go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version-file: 'go.mod'
- name: Create build directory
run: |
set -eux
mkdir bin
- name: Make GOCOVERDIR
run: |
set -eux
mkdir -p coverage
cd coverage
echo "GOCOVERDIR=$(pwd)" >> "${GITHUB_ENV}"
if: env.GOCOVERAGE == 'true'
- name: Build static lxc
env:
CGO_ENABLED: 0
COVER: ${{ ( env.GOCOVERDIR != '' ) && '-cover' || '' }}
run: |
set -eux
# Using `go env -w` to avoid dealing with setting variables on Windows
go env -w GOARCH=arm64
go build -ldflags "-s -w" -trimpath -o bin/lxc.aarch64 ${COVER} ./lxc
go env -w GOARCH=amd64
go build -ldflags "-s -w" -trimpath -o bin/lxc.x86_64 ${COVER} ./lxc
- name: Build static lxd-benchmark
if: runner.os == 'Linux'
env:
CGO_ENABLED: 0
COVER: ${{ ( env.GOCOVERDIR != '' ) && '-cover' || '' }}
run: |
set -eux
GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o bin/lxd-benchmark.x86_64 ${COVER} ./lxd-benchmark
GOARCH=arm64 go build -ldflags "-s -w" -trimpath -o bin/lxd-benchmark.aarch64 ${COVER} ./lxd-benchmark
- name: Build static lxd-migrate
if: runner.os == 'Linux'
env:
CGO_ENABLED: 0
COVER: ${{ ( env.GOCOVERDIR != '' ) && '-cover' || '' }}
run: |
set -eux
GOARCH=amd64 go build -ldflags "-s -w" -trimpath -o bin/lxd-migrate.x86_64 ${COVER} ./lxd-migrate
GOARCH=arm64 go build -ldflags "-s -w" -trimpath -o bin/lxd-migrate.aarch64 ${COVER} ./lxd-migrate
- name: Unit tests (client)
env:
CGO_ENABLED: 0
COVER: ${{ ( env.GOCOVERDIR != '' ) && '-cover' || '' }}
run: |
set -eux
[ -n "${COVER}" ] && COVER="${COVER} -test.gocoverdir=${GOCOVERDIR}"
go test -mod=readonly -v ./client/... ${COVER}
- name: Unit tests (lxc)
env:
CGO_ENABLED: 0
COVER: ${{ ( env.GOCOVERDIR != '' ) && '-cover' || '' }}
run: |
set -eux
[ -n "${COVER}" ] && COVER="${COVER} -test.gocoverdir=${GOCOVERDIR}"
go test -mod=readonly -v ./lxc/... ${COVER}
- name: Unit tests (shared)
env:
CGO_ENABLED: 0
COVER: ${{ ( env.GOCOVERDIR != '' ) && '-cover' || '' }}
run: |
set -eux
[ -n "${COVER}" ] && COVER="${COVER} -test.gocoverdir=${GOCOVERDIR}"
go test -mod=readonly -v ./shared/... ${COVER}
- name: Upload coverage data
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: coverage-clients-${{ runner.os }}
path: ${{env.GOCOVERDIR}}
retention-days: 1
if: env.GOCOVERDIR != ''
- name: Upload lxc client artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
if: ${{ github.event_name == 'push' }}
continue-on-error: true
with:
name: lxd-clients-${{ runner.os }}
path: bin/
ui-e2e-tests:
name: UI e2e tests
runs-on: ubuntu-24.04
needs: [code-tests, documentation]
if: ${{ ( github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' || github.event_name == 'push' ) && github.ref_name == 'main' && github.repository == 'canonical/lxd' }}
env:
LD_LIBRARY_PATH: "/home/runner/go/bin/dqlite/libs/"
LXD_DIR: "/var/lib/lxd"
LXD_OIDC_CLIENT_ID: ${{ secrets.LXD_UI_OIDC_TEST_CLIENT_ID }}
LXD_OIDC_CLIENT_SECRET: ${{ secrets.LXD_UI_OIDC_TEST_CLIENT_SECRET }}
LXD_OIDC_ISSUER: ${{ secrets.LXD_UI_OIDC_TEST_ISSUER }}
LXD_OIDC_AUDIENCE: ${{ secrets.LXD_UI_OIDC_TEST_AUDIENCE }}
LXD_OIDC_USER: ${{ secrets.LXD_UI_OIDC_TEST_USER }}
LXD_OIDC_PASSWORD: ${{ secrets.LXD_UI_OIDC_TEST_PASSWORD }}
LXD_OIDC_GROUPS_CLAIM: "lxd-idp-groups"
steps:
- name: Checkout code
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Tune disk performance
uses: ./.github/actions/tune-disk-performance
- name: Checkout LXD-UI
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
repository: 'canonical/lxd-ui'
ref: main
path: lxd-ui
persist-credentials: false
- name: Install Dotrun
run: sudo pip3 install dotrun
- name: Install LXD-UI dependencies
run: |
set -eux
sudo chmod 0777 ./lxd-ui
cd lxd-ui
dotrun install
- uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: 22
- name: Install Playwright Browsers
run: |
set -eux
cd lxd-ui
npx playwright install --with-deps chromium
- name: Install runtime dependencies
uses: ./.github/actions/install-lxd-runtimedeps
with:
optional: true
# Restore the cache warmed in code-tests job
- name: Build or restore dqlite/liblxc dependencies
uses: ./.github/actions/cache-dqlite-liblxc
# Restore the cache warmed in code-tests job
- name: Download minio/mc
uses: ./.github/actions/download-minio
- name: Download system test dependencies
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: system-test-deps
merge-multiple: true
path: /home/runner/go/bin
- name: Prepare for running LXD daemon
run: |
set -eux
# Update env variables for liblxc
LIBLXC_ARCH_LIBS="$(readlink -e /home/runner/go/bin/liblxc/libs/*-linux-gnu)"
echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${LIBLXC_ARCH_LIBS}" >> "${GITHUB_ENV}"
- name: Set exec perms on LXD binaries
run: |
set -eux
ls -lR /home/runner/go/bin/
chmod uog+x /home/runner/go/bin/*
- name: Download docs (for the objects.inv.txt file to be available for the e2e tests)
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: documentation
merge-multiple: true
path: doc/_build
- name: Make GOCOVERDIR
run: |
set -eux
mkdir -p coverage
cd coverage
echo "GOCOVERDIR=$(pwd)" >> "${GITHUB_ENV}"
if: env.GOCOVERAGE == 'true'
- name: Run LXD daemon
run: |
set -eux
chmod +x ~
echo "root:1000000:1000000000" | sudo tee /etc/subuid /etc/subgid
export LXD_DOCUMENTATION="/home/runner/work/lxd/lxd/doc/_build/"
export PATH="/home/runner/go/bin:$PATH"
sudo rm -rf /var/lib/lxd
sudo --preserve-env=PATH,GOPATH,GOCOVERDIR,LD_LIBRARY_PATH,LXD_DOCUMENTATION $(go env GOPATH)/bin/lxd --group sudo &
- name: Run LXD-UI
env:
ENVIRONMENT: devel
PORT: 8407
LXD_UI_BACKEND_IP: 172.17.0.1
run: |
set -eux
cd lxd-ui
dotrun &
curl --head --fail --retry-delay 2 --retry 100 --retry-connrefused --insecure https://localhost:${PORT}
- name: Setup LXD
shell: bash
run: |
set -eux
export PATH="/home/runner/go/bin:$PATH"
sudo chown $USER /var/lib/lxd/unix.socket
sudo ln -s /home/runner/go/bin/lxc /usr/bin/lxc
lxc storage create default zfs
lxc profile device add default root disk path=/ pool=default
lxc network create local-network
lxc profile device add default eth0 nic network=local-network
lxc config set core.https_address "[::]:8443"
lxc config set cluster.https_address "127.0.0.1"
lxc config set user.show_permissions=true
lxc config trust add lxd-ui/keys/lxd-ui.crt
- name: Setup for LXD-UI tests
shell: bash
run: |
set -eux
export PATH="/home/runner/go/bin:$PATH"
./lxd-ui/tests/scripts/setup_test
- name: Test basic LXD functionality
shell: bash
run: |
set -eux
export PATH="/home/runner/go/bin:$PATH"
# launch a test instance
./test/deps/import-busybox --alias testimage
lxc launch testimage --quiet c1 -d root,size=32MiB || { lxc info --show-log c1; false; }
# cleanup
lxc delete -f c1
lxc image delete testimage
- name: Run Playwright tests
env:
TARGET: >-
${{ fromJson('{
"main": "latest-edge",
"stable-5.0": "5.0-edge",
"stable-5.21": "5.21-edge",
}')[github.ref_name] }}
run: |
set -eux
cd lxd-ui
sudo chown $USER -R /home/runner/.config
export PATH="/home/runner/go/bin:$PATH"
export CI=true
export DISABLE_VM_TESTS=true
npx playwright test --project "chromium:lxd-${TARGET:-latest-edge}:unclustered"
- name: Upload lxd-ui test artifacts
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
if: always()
with:
name: lxd-ui-test-report
path: lxd-ui/blob-report
retention-days: 14
- name: Shutdown LXD daemon
run: |
set -eux
export PATH="/home/runner/go/bin:$PATH"
sudo --preserve-env=PATH,GOPATH,GOCOVERDIR,LD_LIBRARY_PATH $(go env GOPATH)/bin/lxd shutdown
- name: Upload coverage data
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: coverage-ui-e2e-tests
path: ${{env.GOCOVERDIR}}
retention-days: 1
if: env.GOCOVERDIR != ''
documentation:
name: Documentation
runs-on: ubuntu-24.04
if: github.event_name == 'workflow_dispatch' || github.repository == 'canonical/lxd'
needs: code-tests
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
# A non-shallow clone is needed for the sitemap generation
fetch-depth: 0
persist-credentials: false
- name: Install Go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version-file: 'go.mod'
- name: Install Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
cache: 'pip' # caching pip dependencies
cache-dependency-path: |
doc/.sphinx/build_requirements.py
doc/.sphinx/requirements.txt
doc/custom_conf.py
python-version: '3.x' # satisfied by any 3.x version already installed
- name: Install dependencies
run: |
set -eux
sudo apt-get install aspell aspell-en
sudo snap install mdl
- name: Build docs (Sphinx)
run: |
set -eux
make doc
if [ -s doc/.sphinx/warnings.txt ]; then cat doc/.sphinx/warnings.txt; exit 1; fi
- name: Run markdown linter
run: |
set -eux
make doc-lint
- name: Run spell checker
run: |
set -eux
make doc-spellcheck
- name: Run inclusive naming checker
uses: get-woke/woke-action@b2ec032c4a2c912142b38a6a453ad62017813ed0 # v0
with:
fail-on-error: true
woke-args: "*.md **/*.md -c https://github.com/canonical/Inclusive-naming/raw/main/config.yml"
- name: Upload documentation artifacts
if: always()
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: documentation
path: doc/_build
retention-days: 5
documentation-linkcheck:
name: Documentation link check
runs-on: ubuntu-24.04
needs: documentation
# Run link checker during manual or scheduled CI runs only
if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }}
steps:
- name: Checkout
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- name: Install Go
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
go-version-file: 'go.mod'
- name: Install Python
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
cache: 'pip' # caching pip dependencies
cache-dependency-path: |
doc/.sphinx/build_requirements.py
doc/.sphinx/requirements.txt
doc/custom_conf.py
python-version: '3.x' # satisfied by any 3.x version already installed
- name: Build LXD client
run: make client
- name: Download built docs
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: documentation
merge-multiple: true
path: doc/_build
- name: Run link checker
shell: 'script -q -e -c "export TERM=xterm-256color; bash {0}"'
run: |
set -eux
make doc-linkcheck
snap:
name: Trigger snap edge build
runs-on: ubuntu-24.04
needs: [code-tests, system-tests, client, documentation]
if: ${{ github.repository == 'canonical/lxd' && github.event_name == 'push' && github.actor != 'dependabot[bot]' }}
env:
SSH_AUTH_SOCK: /tmp/ssh_agent.sock
PACKAGE: "lxd"
REPO: "git+ssh://[email protected]/~lxd-snap/lxd"
BRANCH: >-
${{ fromJson('{
"main": "latest-edge",
"stable-5.21": "5.21-edge",
"stable-5.0": "5.0-edge",
}')[github.ref_name] }}
steps:
- name: Checkout code
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0
with:
persist-credentials: false
- uses: ./.github/actions/lp-snap-build
with:
ssh-key: "${{ secrets.LAUNCHPAD_LXD_BOT_KEY}}"
- name: Trigger Launchpad snap build
run: |
set -eux
echo "${PATH}"
localRev="$(git rev-parse HEAD)"
cd ~/"${PACKAGE}-pkg-snap-lp"
lxd-snapcraft -package "${PACKAGE}" -set-version "git-${localRev:0:7}" -set-source-commit "${localRev}"
git add --all
git commit --all --quiet -s --allow-empty -m "Automatic upstream build (${BRANCH})" -m "Upstream commit: ${localRev}"
git show
git push --quiet