Skip to content

Multipass clone

Multipass clone #6676

Workflow file for this run

name: Linux
on:
push:
branches:
- main
- release/[0-9]+.[0-9]+
tags:
- v[0-9]+.[0-9]+.[0-9]+
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
merge_group:
types: [checks_requested]
concurrency:
group: ${{ github.workflow }}-${{ github.event.number && format('pr{0}', github.event.number) || github.run_id }}
cancel-in-progress: true
jobs:
Lint:
runs-on: ubuntu-latest
if: ${{ contains('pull_request merge_group', github.event_name) }}
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Lint the code
uses: ./.github/actions/lint
GetMatrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Determine job matrix
id: set-matrix
run: |
set -euo pipefail
MATRIX='{"build-type": "Debug"}
{"build-type": "Clang"}
{"build-type": "Release"}'
if ${{ github.event_name != 'merge_group' }}; then
MATRIX+='{"build-type": "Coverage" }'
fi
echo "${MATRIX}" | jq -cs '{"include": . }' | awk '{ print "matrix=" $0 }' >> $GITHUB_OUTPUT
BuildAndTest:
needs: [Lint, GetMatrix]
# Allow skipped Lint
# Let Lint fail on pull requests
if: |
${{
success()
|| needs.Lint.result == 'skipped'
|| ( needs.Lint.result == 'failure'
&& github.event_name == 'pull_request' )
}}
outputs:
label: ${{ steps.build-params.outputs.label }}
channel: ${{ steps.build-params.outputs.channel }}
snap-file: ${{ steps.build-snap.outputs.snap-file }}
strategy:
matrix: ${{ fromJSON(needs.GetMatrix.outputs.matrix) }}
runs-on: ubuntu-latest
env:
SNAPCRAFT_BUILD_INFO: 1
timeout-minutes: 120
steps:
- name: Install Snapcraft
uses: samuelmeuli/action-snapcraft@v2
- name: Install LXD
uses: canonical/setup-lxd@87f9a0dbf8855632e12fad0a45795338e4e97d12
- name: Check out code
uses: actions/checkout@v4
with:
# Need to fetch it all for submodules to work.
fetch-depth: 0
- name: Check out tags and submodules
uses: ./.github/actions/checkout
- name: Determine build parameters
id: build-params
uses: ./.github/actions/build-params
- name: Patch
env:
PATCH_PREFIX: .github/workflows/linux
run: |
[ ! -f ${PATCH_PREFIX}.patch ] || patch -p1 --no-backup-if-mismatch < ${PATCH_PREFIX}.patch
[ ! -f ${PATCH_PREFIX}-${{ matrix.build-type }}.patch ] || patch -p1 --no-backup-if-mismatch < ${PATCH_PREFIX}-${{ matrix.build-type }}.patch
- name: Set up vcpkg
id: setup-vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgDirectory: '${{ github.workspace }}/3rd-party/vcpkg'
- name: Set up CCache
id: setup-ccache
run: |
sudo apt-get install ccache
ccache --max-size=2G
mkdir -p ${HOME}/.ccache
/snap/bin/lxc profile device add default ccache disk source=${HOME}/.ccache/ path=/root/.ccache
# Find common base between main and HEAD to use as cache key.
git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules origin main
echo "key=$( git merge-base origin/main ${{ github.sha }} )" >> $GITHUB_OUTPUT
- name: CCache
uses: actions/cache@v4
with:
key: ccache-${{ runner.os }}-${{ matrix.build-type }}-${{ steps.setup-ccache.outputs.key }}
restore-keys: |
ccache-${{ runner.os }}-${{ matrix.build-type }}-
path: ~/.ccache
- name: Set up coverage
id: coverage-setup
if: ${{ matrix.build-type == 'Coverage' }}
run: |
MULTIPASS_PART=${HOME}/multipass_part
mkdir --parents ${MULTIPASS_PART}
/snap/bin/lxc profile device add default build disk source=${MULTIPASS_PART} path=/root/parts/multipass
echo "build=${MULTIPASS_PART}/build" >> $GITHUB_OUTPUT
- name: Build
run: |
# Inject the build label.
sed -i "/cmake-parameters:/a \ - -DMULTIPASS_BUILD_LABEL=${{ steps.build-params.outputs.label }}" snap/snapcraft.yaml
# Inject vcpkg GH Actions cache env vars if they exist
if [ -n "$ACTIONS_CACHE_URL" ]; then
sed -i "/build-environment:/a \ - ACTIONS_CACHE_URL: ${ACTIONS_CACHE_URL}" snap/snapcraft.yaml
fi
if [ -n "ACTIONS_RUNTIME_TOKEN" ]; then
sed -i "/build-environment:/a \ - ACTIONS_RUNTIME_TOKEN: ${ACTIONS_RUNTIME_TOKEN}" snap/snapcraft.yaml
fi
if [ -n "VCPKG_BINARY_SOURCES" ]; then
sed -i "/build-environment:/a \ - VCPKG_BINARY_SOURCES: ${VCPKG_BINARY_SOURCES}" snap/snapcraft.yaml
fi
# Build the `multipass` part.
/snap/bin/snapcraft build --use-lxd multipass
- name: Clear CCache stats
run: ccache --show-stats --zero-stats
- name: Test
if: ${{ matrix.build-type == 'Debug' }}
timeout-minutes: 2
run: |
instance_name=`/snap/bin/lxc --project snapcraft --format=csv --columns=n list | grep multipass`
/snap/bin/lxc --project snapcraft start $instance_name
/snap/bin/lxc --project snapcraft exec $instance_name -- \
env CTEST_OUTPUT_ON_FAILURE=1 \
LD_LIBRARY_PATH=/root/stage/usr/lib/x86_64-linux-gnu/:/root/stage/lib/:/root/parts/multipass/build/lib/ \
/root/parts/multipass/build/bin/multipass_tests
- name: Measure coverage
id: measure-coverage
if: ${{ matrix.build-type == 'Coverage' }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
timeout-minutes: 5
run: |
instance_name=`/snap/bin/lxc --project snapcraft --format=csv --columns=n list | grep multipass`
/snap/bin/lxc --project snapcraft start $instance_name
# Wait for snapd to actually finish- in particular, that snaps are mounted
timeout 10 sh -c \
'while [ "$( /snap/bin/lxc --project snapcraft exec '$instance_name' -- \
systemctl show --property=ActiveState snapd )" != "ActiveState=active" ]; do sleep 1; done'
# Wait for LXD container network to be ready like Snapcraft does
timeout 40 sh -c \
'while /snap/bin/lxc --project snapcraft exec '$instance_name' -- getent hosts multipass.run ; \
[ $? -ne 0 ] ; do sleep 1; done'
# The following 2 commands workaround the issue in 20.04 where the default parsing of the coverage
# JSON file is extremely slow. This makes is use fast parsing.
/snap/bin/lxc --project snapcraft exec $instance_name -- apt-get -y install libjson-xs-perl sudo
/snap/bin/lxc --project snapcraft exec $instance_name -- \
sh -c "sudo sed -i \"s/use JSON::PP/use JSON::XS/\" \`which geninfo\`"
/snap/bin/lxc --project snapcraft exec $instance_name -- \
env CTEST_OUTPUT_ON_FAILURE=1 \
cmake --build /root/parts/multipass/build --target covreport
bash <(curl -s https://codecov.io/bash) -Z -s ${{ steps.coverage-setup.outputs.build }}
- name: Continue on Error comment
uses: mainmatter/continue-on-error-comment@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
outcome: ${{ steps.measure-coverage.outcome }}
test-id: Error with measuring coverage in ${{ matrix.build-type }} build
- name: Build and verify the snap
id: build-snap
if: ${{ matrix.build-type == 'Release' }}
env:
SNAP_ENFORCE_RESQUASHFS: 0
run: |
# Actually build the snap.
/snap/bin/snapcraft --use-lxd
sudo snap install review-tools
/snap/bin/review-tools.snap-review --plugs=snap/local/plugs.json *.snap
echo "snap-file=$( ls *.snap )" >> $GITHUB_OUTPUT
- name: Upload the snap
uses: actions/upload-artifact@v4
if: ${{ matrix.build-type == 'Release' }}
with:
name: ${{ steps.build-snap.outputs.snap-file }}
path: ${{ steps.build-snap.outputs.snap-file }}
if-no-files-found: error
# Publish the snap to the store if a channel was determined and we have access to secrets.
Publish-Snap:
needs: BuildAndTest
# Need to explicitly continue on Lint getting skipped.
if: ${{
!failure()
&& !cancelled()
&& needs.BuildAndTest.outputs.channel != ''
&& (github.event_name == 'push'
|| github.event_name == 'merge_group'
|| github.event.pull_request.head.repo.full_name == github.repository)
}}
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Download the built snap
uses: actions/download-artifact@v4
with:
name: ${{ needs.BuildAndTest.outputs.snap-file }}
- name: Install Snapcraft and log in
uses: samuelmeuli/action-snapcraft@v2
- name: Publish the snap
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }}
run: |
snapcraft upload *.snap --release ${{ needs.BuildAndTest.outputs.channel }}
# Dispatch to the private side
Dispatch:
needs:
- BuildAndTest
- Publish-Snap
# Only dispatch if we have access to secrets.
# Need to explicitly continue on Lint getting skipped.
if: ${{
!failure()
&& !cancelled()
&& (github.event_name == 'push'
|| github.event_name == 'merge_group'
|| github.event.pull_request.head.repo.full_name == github.repository)
}}
runs-on: ubuntu-latest
steps:
- name: Determine dispatch parameters
id: dispatch-params
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
echo "head_ref=${{ github.head_ref }}" >> $GITHUB_OUTPUT
echo "head_sha=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
else
echo "head_ref=${{ github.ref }}" >> $GITHUB_OUTPUT
echo "head_sha=${{ github.sha }}" >> $GITHUB_OUTPUT
fi
- name: Dispatch Linux integration tests
if: ${{ github.event_name == 'push' }}
uses: Saviq/workflow-dispatch@dist
with:
token: ${{ secrets.PRIVATE_GITHUB_TOKEN }}
workflow: Integration
ref: ${{ steps.dispatch-params.outputs.ref }}
sha: ${{ steps.dispatch-params.outputs.sha }}
inputs: |
{
"snap-channel": "${{ needs.BuildAndTest.outputs.channel }}"
}
# This action will fail if `ref` moved on from `sha` to avoid mistargeting Integration runs.
continue-on-error: true
- name: Dispatch macOS and Windows builds
uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.PRIVATE_GITHUB_TOKEN }}
repository: ${{ secrets.PRIVATE_GITHUB_REPO }}
event-type: public_build
client-payload: |
{
"repository": "${{ github.repository }}",
"head_ref": "${{ steps.dispatch-params.outputs.head_ref }}",
"head_sha": "${{ steps.dispatch-params.outputs.head_sha }}",
"ref": "${{ github.ref }}",
"sha": "${{ github.sha }}",
"draft": "${{ github.event.pull_request.draft }}",
"label": "${{ needs.BuildAndTest.outputs.label }}",
"dispatch_ci": "${{ github.event_name == 'push' }}"
}