tests: run static analysis for prs in self-hosted runners (#13855) #3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Tests | |
on: | |
pull_request: | |
branches: [ "master", "release/**" ] | |
push: | |
# we trigger runs on master branch, but we do not run spread on master | |
# branch, the master branch runs are just for unit tests + codecov.io | |
branches: [ "master","release/**" ] | |
# XXX we suspect that the whenever the labeler workflow executes successfully | |
# it will trigger another workflow of tests on master, temporarily disable to | |
# see if that improves the situation | |
# workflow_run: | |
# workflows: ["Pull Request Labeler"] | |
# types: | |
# - completed | |
concurrency: | |
group: ${{ github.head_ref || github.run_id }} | |
cancel-in-progress: true | |
jobs: | |
snap-builds: | |
runs-on: ubuntu-20.04 | |
# only build the snap for pull requests, it's not needed on release branches | |
# or on master since we have launchpad build recipes which do this already | |
if: ${{ github.event_name == 'pull_request' }} | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
- name: Build snapd snap | |
uses: snapcore/action-build@v1 | |
with: | |
snapcraft-channel: 4.x/candidate | |
- name: Check built artifact | |
run: | | |
unsquashfs snapd*.snap meta/snap.yaml usr/lib/snapd/ | |
if cat squashfs-root/meta/snap.yaml | grep -q "version:.*dirty.*"; then | |
echo "PR produces dirty snapd snap version" | |
cat squashfs-root/usr/lib/snapd/dirty-git-tree-info.txt | |
exit 1 | |
elif cat squashfs-root/usr/lib/snapd/info | grep -q "VERSION=.*dirty.*"; then | |
echo "PR produces dirty internal snapd info version" | |
cat squashfs-root/usr/lib/snapd/info | |
cat squashfs-root/usr/lib/snapd/dirty-git-tree-info.txt | |
exit 1 | |
fi | |
- name: Uploading snapd snap artifact | |
uses: actions/upload-artifact@v3 | |
with: | |
name: snap-files | |
path: "*.snap" | |
cache-build-deps: | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
with: | |
# needed for git commit history | |
fetch-depth: 0 | |
# NOTE: checkout the code in a fixed location, even for forks, as this | |
# is relevant for go's import system. | |
path: ./src/github.com/snapcore/snapd | |
# Fetch base ref, needed for golangci-lint | |
- name: Fetching base ref ${{ github.base_ref }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd | |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} | |
# golang latest ensures things work on the edge | |
- name: Download Debian dependencies | |
run: | | |
sudo apt clean | |
sudo apt update | |
sudo apt build-dep -d -y ${{ github.workspace }}/src/github.com/snapcore/snapd | |
# for indent | |
sudo apt install texinfo autopoint | |
- name: Copy dependencies | |
run: | | |
sudo tar cvf cached-apt.tar /var/cache/apt | |
- name: upload Debian dependencies | |
uses: actions/upload-artifact@v3 | |
with: | |
name: debian-dependencies | |
path: ./cached-apt.tar | |
static-checks: | |
runs-on: ubuntu-latest | |
needs: [cache-build-deps] | |
env: | |
GOPATH: ${{ github.workspace }} | |
# Set PATH to ignore the load of magic binaries from /usr/local/bin And | |
# to use the go snap automatically. Note that we install go from the | |
# snap in a step below. Without this we get the GitHub-controlled latest | |
# version of go. | |
PATH: /snap/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:${{ github.workspace }}/bin | |
GOROOT: "" | |
GITHUB_PULL_REQUEST: ${{ github.event.number }} | |
strategy: | |
# we cache successful runs so it's fine to keep going | |
fail-fast: false | |
matrix: | |
gochannel: | |
- 1.18 | |
- latest/stable | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
with: | |
# needed for git commit history | |
fetch-depth: 0 | |
# NOTE: checkout the code in a fixed location, even for forks, as this | |
# is relevant for go's import system. | |
path: ./src/github.com/snapcore/snapd | |
# Fetch base ref, needed for golangci-lint | |
- name: Fetching base ref ${{ github.base_ref }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd | |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} | |
- name: Download Debian dependencies | |
uses: actions/download-artifact@v3 | |
with: | |
name: debian-dependencies | |
path: ./debian-deps/ | |
- name: Copy dependencies | |
run: | | |
test -f ./debian-deps/cached-apt.tar | |
sudo tar xvf ./debian-deps/cached-apt.tar -C / | |
- name: Install Debian dependencies | |
run: | | |
sudo apt update | |
sudo apt build-dep -y ${{ github.workspace }}/src/github.com/snapcore/snapd | |
# golang latest ensures things work on the edge | |
- name: Install the go snap | |
run: | | |
sudo snap install --classic --channel=${{ matrix.gochannel }} go | |
- name: Install ShellCheck as a snap | |
run: | | |
sudo apt-get remove --purge shellcheck | |
sudo snap install shellcheck | |
- name: Get C vendoring | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/c-vendor && ./vendor.sh | |
- name: golangci-lint | |
if: ${{ matrix.gochannel == 'latest/stable' }} | |
uses: golangci/golangci-lint-action@v3 | |
with: | |
# version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` | |
# to use the latest version | |
version: v1.55.2 | |
working-directory: ./src/github.com/snapcore/snapd | |
# show only new issues | |
# use empty path prefix to make annotations work | |
args: --new-from-rev=${{ github.base_ref }} --path-prefix= | |
# skip all additional steps | |
skip-pkg-cache: true | |
skip-build-cache: true | |
# XXX: does no work with working-directory | |
# only-new-issues: true | |
- name: Get changed files | |
id: changed-files | |
uses: tj-actions/[email protected] | |
with: | |
path: ./src/github.com/snapcore/snapd | |
- name: Save changes files | |
run: | | |
CHANGED_FILES="${{ steps.changed-files.outputs.all_changed_files }}" | |
echo "CHANGED_FILES=$CHANGED_FILES" >> $GITHUB_ENV | |
echo "The changed files found are: $CHANGED_FILES" | |
- name: Run static checks | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd || exit 1 | |
# run gofmt checks only with Go 1.18 | |
if [ "${{ matrix.gochannel }}" != "1.18" ]; then | |
export SKIP_GOFMT=1 | |
echo "Formatting checks will be skipped due to the use of Go version ${{ matrix.gochannel }}" | |
fi | |
sudo apt-get install -y python3-yamlordereddictloader | |
./run-checks --static | |
- name: Cache prebuilt indent | |
id: cache-indent-bin | |
uses: actions/cache@v3 | |
with: | |
path: indent-bin | |
key: ${{ runner.os }}-indent-2.2.13 | |
# build indent 2.2.13 which has this patch | |
# https://git.savannah.gnu.org/cgit/indent.git/commit/?id=22b83d68e9a8b429590f42920e9f473a236123cf | |
- name: Build indent 2.2.13 | |
if: steps.cache-indent-bin.outputs.cache-hit != 'true' | |
run: | | |
sudo apt install texinfo autopoint | |
curl -O https://ftp.gnu.org/gnu/indent/indent-2.2.13.tar.xz | |
tar xvf indent-2.2.13.tar.xz | |
cd indent-2.2.13 | |
autoreconf -if | |
# set prefix in case we want to pack to tar/extract into system | |
./configure --prefix=/opt/indent | |
make -j | |
make install DESTDIR=${{ github.workspace }}/indent-bin | |
find ${{ github.workspace }}/indent-bin -ls | |
- name: Check C source code formatting | |
run: | | |
set -x | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/cmd/ | |
./autogen.sh | |
# apply formatting | |
PATH=${{ github.workspace }}/indent-bin/opt/indent/bin:$PATH make fmt | |
set +x | |
if [ -n "$(git diff --stat)" ]; then | |
git diff | |
echo "C files are not fomratted correctly, run 'make fmt'" | |
echo "make sure to have clang-format and indent 2.2.13+ installed" | |
exit 1 | |
fi | |
branch-static-checks: | |
runs-on: ubuntu-latest | |
needs: [cache-build-deps] | |
if: github.ref != 'refs/heads/master' | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
with: | |
# needed for git commit history | |
fetch-depth: 0 | |
- name: check-branch-ubuntu-daily-spread | |
run: | | |
# Compare the daily system in master and in the current branch | |
wget -q -O test_master.yaml https://raw.githubusercontent.com/snapcore/snapd/master/.github/workflows/test.yaml | |
system_daily="$(yq '.jobs.spread.strategy.matrix.include.[] | select(.group == "ubuntu-daily") | .systems' test_master.yaml)" | |
current_daily="$(yq '.jobs.spread.strategy.matrix.include.[] | select(.group == "ubuntu-daily") | .systems' .github/workflows/test.yaml)" | |
test "$system_daily" == "$current_daily" | |
shell: bash | |
unit-tests: | |
needs: [static-checks] | |
runs-on: ubuntu-22.04 | |
env: | |
GOPATH: ${{ github.workspace }} | |
# Set PATH to ignore the load of magic binaries from /usr/local/bin And | |
# to use the go snap automatically. Note that we install go from the | |
# snap in a step below. Without this we get the GitHub-controlled latest | |
# version of go. | |
PATH: /snap/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:${{ github.workspace }}/bin | |
GOROOT: "" | |
GITHUB_PULL_REQUEST: ${{ github.event.number }} | |
strategy: | |
# we cache successful runs so it's fine to keep going | |
fail-fast: false | |
matrix: | |
gochannel: | |
- 1.18 | |
- latest/stable | |
unit-scenario: | |
- normal | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
with: | |
# needed for git commit history | |
fetch-depth: 0 | |
# NOTE: checkout the code in a fixed location, even for forks, as this | |
# is relevant for go's import system. | |
path: ./src/github.com/snapcore/snapd | |
# Fetch base ref, needed for golangci-lint | |
- name: Fetching base ref ${{ github.base_ref }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd | |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} | |
- name: Download Debian dependencies | |
uses: actions/download-artifact@v3 | |
with: | |
name: debian-dependencies | |
path: ./debian-deps/ | |
- name: Copy dependencies | |
run: | | |
test -f ./debian-deps/cached-apt.tar | |
sudo tar xvf ./debian-deps/cached-apt.tar -C / | |
- name: Install Debian dependencies | |
run: | | |
sudo apt update | |
sudo apt build-dep -y ${{ github.workspace }}/src/github.com/snapcore/snapd | |
# golang latest ensures things work on the edge | |
- name: Install the go snap | |
run: | | |
sudo snap install --classic --channel=${{ matrix.gochannel }} go | |
- name: Get deps | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/ && ./get-deps.sh | |
- name: Build C | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/cmd/ | |
./autogen.sh | |
make -j$(nproc) | |
- name: Build Go | |
run: | | |
go build github.com/snapcore/snapd/... | |
- name: Test C | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/cmd/ && make check | |
- name: Reset code coverage data | |
run: | | |
rm -rf ${{ github.workspace }}/.coverage/ | |
- name: Test Go | |
if: ${{ matrix.unit-scenario == 'normal' }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd || exit 1 | |
./run-checks --unit | |
- name: Upload the coverage results | |
if: ${{ matrix.gochannel != 'latest/stable' }} | |
uses: actions/upload-artifact@v3 | |
with: | |
name: coverage-files | |
path: "${{ github.workspace }}/src/github.com/snapcore/snapd/.coverage/coverage*.cov" | |
# TODO run unit tests of C code | |
unit-tests-special: | |
needs: [static-checks] | |
runs-on: ubuntu-22.04 | |
env: | |
GOPATH: ${{ github.workspace }} | |
# Set PATH to ignore the load of magic binaries from /usr/local/bin And | |
# to use the go snap automatically. Note that we install go from the | |
# snap in a step below. Without this we get the GitHub-controlled latest | |
# version of go. | |
PATH: /snap/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:${{ github.workspace }}/bin | |
GOROOT: "" | |
GITHUB_PULL_REQUEST: ${{ github.event.number }} | |
strategy: | |
# we cache successful runs so it's fine to keep going | |
fail-fast: false | |
matrix: | |
gochannel: | |
- 1.18 | |
- latest/stable | |
unit-scenario: | |
- snapd_debug | |
- withbootassetstesting | |
- nosecboot | |
- faultinject | |
- race | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
with: | |
# needed for git commit history | |
fetch-depth: 0 | |
# NOTE: checkout the code in a fixed location, even for forks, as this | |
# is relevant for go's import system. | |
path: ./src/github.com/snapcore/snapd | |
# Fetch base ref, needed for golangci-lint | |
- name: Fetching base ref ${{ github.base_ref }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd | |
git fetch origin ${{ github.base_ref }}:${{ github.base_ref }} | |
- name: Download Debian dependencies | |
uses: actions/download-artifact@v3 | |
with: | |
name: debian-dependencies | |
path: ./debian-deps/ | |
- name: Copy dependencies | |
run: | | |
test -f ./debian-deps/cached-apt.tar | |
sudo tar xvf ./debian-deps/cached-apt.tar -C / | |
- name: Install Debian dependencies | |
run: | | |
sudo apt update | |
sudo apt build-dep -y ${{ github.workspace }}/src/github.com/snapcore/snapd | |
# golang latest ensures things work on the edge | |
- name: Install the go snap | |
run: | | |
sudo snap install --classic --channel=${{ matrix.gochannel }} go | |
- name: Get deps | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/ && ./get-deps.sh | |
- name: Build C | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/cmd/ | |
./autogen.sh | |
make -j$(nproc) | |
- name: Build Go | |
run: | | |
go build github.com/snapcore/snapd/... | |
- name: Test C | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd/cmd/ && make check | |
- name: Reset code coverage data | |
run: | | |
rm -rf ${{ github.workspace }}/.coverage/ | |
- name: Test Go (SNAPD_DEBUG=1) | |
if: ${{ matrix.unit-scenario == 'snapd_debug' }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd || exit 1 | |
SKIP_DIRTY_CHECK=1 SNAPD_DEBUG=1 ./run-checks --unit | |
- name: Test Go (withbootassetstesting) | |
if: ${{ matrix.unit-scenario == 'withbootassetstesting' }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd || exit 1 | |
SKIP_DIRTY_CHECK=1 GO_BUILD_TAGS=withbootassetstesting ./run-checks --unit | |
- name: Test Go (nosecboot) | |
if: ${{ matrix.unit-scenario == 'nosecboot' }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd || exit 1 | |
echo "Dropping github.com/snapcore/secboot" | |
# use govendor remove so that a subsequent govendor sync does not | |
# install secboot again | |
# ${{ github.workspace }}/bin/govendor remove github.com/snapcore/secboot | |
# ${{ github.workspace }}/bin/govendor remove +unused | |
SKIP_DIRTY_CHECK=1 GO_BUILD_TAGS=nosecboot ./run-checks --unit | |
- name: Test Go (faultinject) | |
if: ${{ matrix.unit-scenario == 'faultinject' }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd || exit 1 | |
SKIP_DIRTY_CHECK=1 GO_BUILD_TAGS=faultinject ./run-checks --unit | |
- name: Test Go (-race) | |
if: ${{ matrix.unit-scenario == 'race' }} | |
run: | | |
cd ${{ github.workspace }}/src/github.com/snapcore/snapd || exit 1 | |
SKIP_DIRTY_CHECK=1 GO_TEST_RACE=1 SKIP_COVERAGE=1 ./run-checks --unit | |
- name: Upload the coverage results | |
if: ${{ matrix.gochannel != 'latest/stable' }} | |
uses: actions/upload-artifact@v3 | |
with: | |
name: coverage-files | |
path: "${{ github.workspace }}/src/github.com/snapcore/snapd/.coverage/coverage*.cov" | |
unit-tests-cross-distro: | |
needs: [static-checks] | |
env: | |
# Set PATH to ignore the load of magic binaries from /usr/local/bin And | |
# to use the go snap automatically. Note that we install go from the | |
# snap in a step below. Without this we get the GitHub-controlled latest | |
# version of go. | |
PATH: /usr/sbin:/usr/bin:/sbin:/bin | |
GITHUB_PULL_REQUEST: ${{ github.event.number }} | |
strategy: | |
fail-fast: false | |
matrix: | |
distro: | |
# TODO add arch? | |
- fedora:39 | |
- opensuse/tumbleweed | |
runs-on: ubuntu-latest | |
container: ${{ matrix.distro }} | |
steps: | |
- name: Checkout code | |
uses: actions/checkout@v4 | |
with: | |
# needed for git commit history | |
fetch-depth: 0 | |
- name: Install dependencies | |
run: | | |
# approximation to handle both typical foo:bar (tagged) and foo/bar | |
# (with implicit :latest) | |
distroname="$(echo "${{ matrix.distro }}" | tr : - | tr / -)" | |
case "${{ matrix.distro }}" in | |
fedora:*) | |
dnf install -y rpmdevtools | |
dnf install -y $(rpmspec -q --buildrequires "./packaging/$distroname/snapd.spec") | |
# TODO these are needed only by cmd/snap-seccomp unit tests, and | |
# should be added to BuildRequires | |
dnf install -y glibc-devel.i686 glibc-static.i686 | |
;; | |
opensuse/*) | |
zypper --non-interactive install -y rpmdevtools rpm-build git | |
zypper --non-interactive install -y $(rpmspec -q --buildrequires "./packaging/$distroname/snapd.spec") | |
;; | |
*) | |
echo "Unsupported distribution variant ${{ matrix.distro }}" | |
exit 1 | |
;; | |
esac | |
- name: Set up test user | |
run: | | |
useradd test-user | |
chown -R test-user:test-user $PWD | |
- name: Unit tests (Go) | |
run: | | |
su test-user sh -c "SKIP_DIRTY_CHECK=1 ./run-checks --unit" | |
- name: Unit tests (C) | |
run: | | |
su test-user sh -c "./mkversion.sh 1337-git && cd ./cmd && ./autogen.sh && make -j && make check" | |
code-coverage: | |
needs: [unit-tests, unit-tests-special] | |
runs-on: ubuntu-20.04 | |
env: | |
GOPATH: ${{ github.workspace }} | |
# Set PATH to ignore the load of magic binaries from /usr/local/bin And | |
# to use the go snap automatically. Note that we install go from the | |
# snap in a step below. Without this we get the GitHub-controlled latest | |
# version of go. | |
PATH: /snap/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:${{ github.workspace }}/bin | |
GOROOT: "" | |
GITHUB_PULL_REQUEST: ${{ github.event.number }} | |
steps: | |
- name: Download the coverage files | |
uses: actions/download-artifact@v3 | |
with: | |
name: coverage-files | |
path: .coverage/ | |
- name: Upload coverage to Codecov | |
uses: codecov/codecov-action@v3 | |
# uploading to codecov occasionally fails, so continue running the test | |
# workflow regardless of the upload | |
continue-on-error: true | |
with: | |
fail_ci_if_error: true | |
flags: unittests | |
name: codecov-umbrella | |
files: .coverage/coverage-*.cov | |
verbose: true | |
spread: | |
needs: [unit-tests] | |
# have spread jobs run on master on PRs only, but on both PRs and pushes to | |
# release branches | |
if: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }} | |
name: ${{ matrix.group }} | |
runs-on: self-hosted | |
strategy: | |
# FIXME: enable fail-fast mode once spread can cancel an executing job. | |
# Disable fail-fast mode as it doesn't function with spread. It seems | |
# that cancelling tasks requires short, interruptible actions and | |
# interrupting spread, notably, does not work today. As such disable | |
# fail-fast while we tackle that problem upstream. | |
fail-fast: false | |
matrix: | |
include: | |
- group: amazon-linux | |
backend: google-central | |
systems: 'amazon-linux-2-64 amazon-linux-2023-64' | |
- group: arch-linux | |
backend: google-central | |
systems: 'arch-linux-64' | |
- group: centos | |
backend: google-central | |
systems: 'centos-7-64 centos-8-64 centos-9-64' | |
- group: debian-req | |
backend: google-central | |
systems: 'debian-11-64' | |
- group: debian-no-req | |
backend: google-central | |
systems: 'debian-12-64 debian-sid-64' | |
- group: fedora | |
backend: google-central | |
systems: 'fedora-38-64 fedora-39-64' | |
- group: opensuse | |
backend: google-central | |
systems: 'opensuse-15.5-64 opensuse-tumbleweed-64' | |
- group: ubuntu-trusty-xenial | |
backend: google | |
systems: 'ubuntu-14.04-64 ubuntu-16.04-64' | |
- group: ubuntu-bionic | |
backend: google | |
systems: 'ubuntu-18.04-32 ubuntu-18.04-64' | |
- group: ubuntu-focal-jammy | |
backend: google | |
systems: 'ubuntu-20.04-64 ubuntu-22.04-64' | |
- group: ubuntu-no-lts | |
backend: google | |
systems: 'ubuntu-23.10-64' | |
- group: ubuntu-daily | |
backend: google | |
systems: 'ubuntu-24.04-64' | |
- group: ubuntu-core-16 | |
backend: google | |
systems: 'ubuntu-core-16-64' | |
- group: ubuntu-core-18 | |
backend: google | |
systems: 'ubuntu-core-18-64' | |
- group: ubuntu-core-20 | |
backend: google | |
systems: 'ubuntu-core-20-64' | |
- group: ubuntu-core-22 | |
backend: google | |
systems: 'ubuntu-core-22-64' | |
- group: ubuntu-core-24 | |
backend: google | |
systems: 'ubuntu-core-24-64' | |
- group: ubuntu-arm | |
backend: google-arm | |
systems: 'ubuntu-20.04-arm-64 ubuntu-core-22-arm-64' | |
- group: ubuntu-secboot | |
backend: google | |
systems: 'ubuntu-secboot-20.04-64' | |
steps: | |
- name: Cleanup job workspace | |
id: cleanup-job-workspace | |
run: | | |
rm -rf "${{ github.workspace }}" | |
mkdir "${{ github.workspace }}" | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
with: | |
# spread uses tags as delta reference | |
fetch-depth: 0 | |
- name: Get previous attempt | |
id: get-previous-attempt | |
run: | | |
echo "previous_attempt=$(( ${{ github.run_attempt }} - 1 ))" >> $GITHUB_OUTPUT | |
shell: bash | |
- name: Get previous cache | |
uses: actions/cache@v3 | |
with: | |
path: "${{ github.workspace }}/.test-results" | |
key: "${{ github.job }}-results-${{ github.run_id }}-${{ matrix.group }}-${{ steps.get-previous-attempt.outputs.previous_attempt }}" | |
- name: Prepare test results env and vars | |
id: prepare-test-results-env | |
run: | | |
# Create test results directories and save vars | |
TEST_RESULTS_DIR="${{ github.workspace }}/.test-results" | |
echo "TEST_RESULTS_DIR=$TEST_RESULTS_DIR" >> $GITHUB_ENV | |
# Save the var with the failed tests file | |
echo "FAILED_TESTS_FILE=$TEST_RESULTS_DIR/failed-tests" >> $GITHUB_ENV | |
# Make sure the test results dirs are created | |
# This step has to be after the cache is restored | |
mkdir -p "$TEST_RESULTS_DIR" | |
- name: Check failed tests to run | |
if: "!contains(github.event.pull_request.labels.*.name, 'Run all')" | |
run: | | |
# Save previous failed test results in FAILED_TESTS env var | |
FAILED_TESTS="" | |
if [ -f "$FAILED_TESTS_FILE" ]; then | |
echo "Failed tests file found" | |
FAILED_TESTS="$(cat $FAILED_TESTS_FILE)" | |
if [ -n "$FAILED_TESTS" ]; then | |
echo "Failed tests to run: $FAILED_TESTS" | |
echo "FAILED_TESTS=$FAILED_TESTS" >> $GITHUB_ENV | |
fi | |
fi | |
- name: Run spread tests | |
if: "!contains(github.event.pull_request.labels.*.name, 'Skip spread')" | |
env: | |
SPREAD_GOOGLE_KEY: ${{ secrets.SPREAD_GOOGLE_KEY }} | |
run: | | |
# Register a problem matcher to highlight spread failures | |
echo "::add-matcher::.github/spread-problem-matcher.json" | |
set -x | |
SPREAD=spread | |
if [[ "${{ matrix.systems }}" =~ -arm- ]]; then | |
SPREAD=spread-arm | |
fi | |
if [[ "${{ matrix.systems }}" =~ amazon-linux-2023 ]]; then | |
# Amazon Linux 2023 has no xdelta, however we cannot disable | |
# xdelta on a per-target basis as it's used in the repack section | |
# of spread.yaml, which is shared by all targets, so all systems | |
# in this batch will not use delta for transferring project data | |
echo "Disabling xdelta support" | |
export NO_DELTA=1 | |
fi | |
RUN_TESTS="" | |
# Save previous failed test results in FAILED_TESTS env var | |
if [ -n "$FAILED_TESTS" ]; then | |
RUN_TESTS="$FAILED_TESTS" | |
else | |
for SYSTEM in ${{ matrix.systems }}; do | |
RUN_TESTS="$RUN_TESTS ${{ matrix.backend }}:$SYSTEM:tests/..." | |
done | |
fi | |
# Run spread tests | |
# "pipefail" ensures that a non-zero status from the spread is | |
# propagated; and we use a subshell as this option could trigger | |
# undesired changes elsewhere | |
echo "Running command: $SPREAD $RUN_TESTS" | |
(set -o pipefail; $SPREAD $RUN_TESTS | tee spread.log) | |
- name: Discard spread workers | |
if: always() | |
run: | | |
shopt -s nullglob; | |
for r in .spread-reuse.*.yaml; do | |
spread -discard -reuse-pid="$(echo "$r" | grep -o -E '[0-9]+')"; | |
done | |
- name: report spread errors | |
if: always() | |
run: | | |
if [ -e spread.log ]; then | |
echo "Running spread log analyzer" | |
issues_metadata='{"source_url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' | |
./tests/lib/external/snapd-testing-tools/utils/log-parser spread.log --print-detail error-debug --output spread-results.json --cut 100 | |
while IFS= read -r line; do | |
if [ ! -z "$line" ]; then | |
echo "Reporting spread error..." | |
./tests/lib/tools/report-mongodb --db-name snapd --db-collection spread_errors --metadata "$issues_metadata" "$line" | |
fi | |
done <<< $(jq -cr '.[] | select( .type == "info") | select( (.info_type == "Error") or (.info_type == "Debug"))' spread-results.json) | |
else | |
echo "No spread log found, skipping errors reporting" | |
fi | |
- name: analyze spread test results | |
if: always() | |
run: | | |
if [ -f spread.log ]; then | |
echo "Running spread log parser" | |
./tests/lib/external/snapd-testing-tools/utils/log-parser spread.log --output spread-results.json | |
echo "Determining which tests were executed" | |
RUN_TESTS="" | |
for SYSTEM in ${{ matrix.systems }}; do | |
RUN_TESTS="$RUN_TESTS ${{ matrix.backend }}:$SYSTEM:tests/..." | |
done | |
if [ -n "$FAILED_TESTS" ]; then | |
RUN_TESTS="$FAILED_TESTS" | |
fi | |
echo "Running spread log analyzer" | |
./tests/lib/external/snapd-testing-tools/utils/log-analyzer list-reexecute-tasks "$RUN_TESTS" spread-results.json > "$FAILED_TESTS_FILE" | |
echo "List of failed tests saved" | |
cat "$FAILED_TESTS_FILE" | |
else | |
echo "No spread log found, saving empty list of failed tests" | |
touch "$FAILED_TESTS_FILE" | |
fi | |
- name: save spread test results to cache | |
if: always() | |
uses: actions/cache/save@v3 | |
with: | |
path: "${{ github.workspace }}/.test-results" | |
key: "${{ github.job }}-results-${{ github.run_id }}-${{ matrix.group }}-${{ github.run_attempt }}" | |
spread-nested: | |
needs: [unit-tests] | |
# have spread jobs run on master on PRs only, but on both PRs and pushes to | |
# release branches | |
if: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }} | |
runs-on: self-hosted | |
strategy: | |
# FIXME: enable fail-fast mode once spread can cancel an executing job. | |
# Disable fail-fast mode as it doesn't function with spread. It seems | |
# that cancelling tasks requires short, interruptible actions and | |
# interrupting spread, notably, does not work today. As such disable | |
# fail-fast while we tackle that problem upstream. | |
fail-fast: false | |
matrix: | |
system: | |
- ubuntu-16.04-64 | |
- ubuntu-18.04-64 | |
- ubuntu-20.04-64 | |
- ubuntu-22.04-64 | |
- ubuntu-24.04-64 | |
steps: | |
- name: Cleanup job workspace | |
id: cleanup-job-workspace | |
run: | | |
rm -rf "${{ github.workspace }}" | |
mkdir "${{ github.workspace }}" | |
- name: Checkout code | |
uses: actions/checkout@v3 | |
- name: Get previous attempt | |
id: get-previous-attempt | |
run: | | |
echo "previous_attempt=$(( ${{ github.run_attempt }} - 1 ))" >> $GITHUB_OUTPUT | |
shell: bash | |
- name: Get previous cache | |
uses: actions/cache@v3 | |
with: | |
path: "${{ github.workspace }}/.test-results" | |
key: "${{ github.job }}-results-${{ github.run_id }}-${{ matrix.system }}-${{ steps.get-previous-attempt.outputs.previous_attempt }}" | |
- name: Prepare test results env and vars | |
id: prepare-test-results-env | |
run: | | |
# Create test results directories and save vars | |
TEST_RESULTS_DIR="${{ github.workspace }}/.test-results" | |
echo "TEST_RESULTS_DIR=$TEST_RESULTS_DIR" >> $GITHUB_ENV | |
# Save the var with the failed tests file | |
echo "FAILED_TESTS_FILE=$TEST_RESULTS_DIR/failed-tests" >> $GITHUB_ENV | |
# Make sure the test results dirs are created | |
# This step has to be after the cache is restored | |
mkdir -p "$TEST_RESULTS_DIR" | |
- name: Check failed tests to run | |
if: "!contains(github.event.pull_request.labels.*.name, 'Run all')" | |
run: | | |
# Save previous failed test results in FAILED_TESTS env var | |
FAILED_TESTS="" | |
if [ -f "$FAILED_TESTS_FILE" ]; then | |
echo "Failed tests file found" | |
FAILED_TESTS="$(cat $FAILED_TESTS_FILE)" | |
if [ -n "$FAILED_TESTS" ]; then | |
echo "Failed tests to run: $FAILED_TESTS" | |
echo "FAILED_TESTS=$FAILED_TESTS" >> $GITHUB_ENV | |
fi | |
fi | |
- name: Collect PR labels | |
id: collect-pr-labels | |
env: | |
GH_TOKEN: ${{ github.token }} | |
run: | | |
LABELS="$(gh api -H 'Accept: application/vnd.github+json' /repos/snapcore/snapd/issues/${{ github.event.pull_request.number }}/labels | jq '[.[].name] | join(",")')" | |
echo "labels=$LABELS" >> $GITHUB_OUTPUT | |
echo "Collected labels: $LABELS" | |
shell: bash | |
- name: Run spread tests | |
# run if the commit is pushed to the release/* branch or there is a 'Run | |
# nested' label set on the PR | |
if: "contains(steps.collect-pr-labels.outputs.labels, 'Run nested') || contains(github.ref, 'refs/heads/release/')" | |
env: | |
SPREAD_GOOGLE_KEY: ${{ secrets.SPREAD_GOOGLE_KEY }} | |
run: | | |
# Register a problem matcher to highlight spread failures | |
echo "::add-matcher::.github/spread-problem-matcher.json" | |
export NESTED_BUILD_SNAPD_FROM_CURRENT=true | |
export NESTED_ENABLE_KVM=true | |
BACKEND=google-nested | |
SPREAD=spread | |
if [[ "${{ matrix.system }}" =~ -arm- ]]; then | |
BACKEND=google-nested-arm | |
SPREAD=spread-arm | |
fi | |
RUN_TESTS="$BACKEND:${{ matrix.system }}:tests/nested/..." | |
if [ -n "$FAILED_TESTS" ]; then | |
RUN_TESTS="$FAILED_TESTS" | |
fi | |
# Run spread tests | |
# "pipefail" ensures that a non-zero status from the spread is | |
# propagated; and we use a subshell as this option could trigger | |
# undesired changes elsewhere | |
(set -o pipefail; spread $RUN_TESTS | tee spread.log) | |
- name: Discard spread workers | |
if: always() | |
run: | | |
shopt -s nullglob; | |
for r in .spread-reuse.*.yaml; do | |
spread -discard -reuse-pid="$(echo "$r" | grep -o -E '[0-9]+')"; | |
done | |
- name: report spread errors | |
if: always() | |
run: | | |
if [ -e spread.log ]; then | |
echo "Running spread log analyzer" | |
issues_metadata='{"source_url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}' | |
./tests/lib/external/snapd-testing-tools/utils/log-parser spread.log --print-detail error --output spread-results.json --cut 100 | |
while IFS= read -r line; do | |
if [ ! -z "$line" ]; then | |
echo "Reporting spread error..." | |
./tests/lib/tools/report-mongodb --db-name snapd --db-collection spread_errors --metadata "$issues_metadata" "$line" | |
fi | |
done <<< $(jq -cr '.[] | select( .type == "info") | select( .info_type == "Error")' spread-results.json) | |
else | |
echo "No spread log found, skipping errors reporting" | |
fi | |
- name: analyze spread test results | |
if: always() | |
run: | | |
if [ -f spread.log ]; then | |
echo "Running spread log parser" | |
./tests/lib/external/snapd-testing-tools/utils/log-parser spread.log --output spread-results.json | |
echo "Determining which tests were executed" | |
RUN_TESTS="google-nested:${{ matrix.system }}:tests/nested/..." | |
if [ -n "$FAILED_TESTS" ]; then | |
RUN_TESTS="$FAILED_TESTS" | |
fi | |
echo "Running spread log analyzer" | |
./tests/lib/external/snapd-testing-tools/utils/log-analyzer list-reexecute-tasks "$RUN_TESTS" spread-results.json > "$FAILED_TESTS_FILE" | |
echo "List of failed tests saved" | |
cat "$FAILED_TESTS_FILE" | |
else | |
echo "No spread log found, saving empty list of failed tests" | |
touch "$FAILED_TESTS_FILE" | |
fi | |
- name: save spread test results to cache | |
if: always() | |
uses: actions/cache/save@v3 | |
with: | |
path: "${{ github.workspace }}/.test-results" | |
key: "${{ github.job }}-results-${{ github.run_id }}-${{ matrix.system }}-${{ github.run_attempt }}" |