Skip to content

CI: Use noble image for QA tests #2219

CI: Use noble image for QA tests

CI: Use noble image for QA tests #2219

Workflow file for this run

name: QA & sanity checks
on:
push:
branches:
- main
tags:
- "*"
pull_request:
env:
DEBIAN_FRONTEND: noninteractive
GO_TESTS_TIMEOUT: 20m
apt_deps: >-
libpam-dev
libglib2.0-dev
libpwquality-dev
test_apt_deps: >-
cracklib-runtime
ffmpeg
openssh-client
openssh-server
# In Rust the grpc stubs are generated at build time
# so we always need to install the protobuf compilers
# when building the NSS crate.
protobuf_compilers: >-
protobuf-compiler
jobs:
go-sanity:
name: "Go: Code sanity"
runs-on: ubuntu-24.04 # ubuntu-latest-runner
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y ${{ env.apt_deps }}
- uses: actions/checkout@v4
- name: Go code sanity check
uses: canonical/desktop-engineering/gh-actions/go/code-sanity@main
with:
golangci-lint-configfile: ".golangci.yaml"
tools-directory: "tools"
- name: Build cmd/authd with withexamplebroker tag
run: |
set -eu
go build -tags withexamplebroker ./cmd/authd
- name: Run PAM client for interactive testing purposes
run: |
set -eu
go run -tags withpamrunner ./pam/tools/pam-runner login --exec-debug
- name: Generate PAM module
run: |
set -eu
find pam -name '*.so' -print -delete
go generate -C pam -x
test -e pam/pam_authd.so
test -e pam/go-exec/pam_authd_exec.so
- name: Generate PAM module with pam_debug tag
run: |
set -eu
find pam -name '*.so' -print -delete
go generate -C pam -x -tags pam_debug
test -e pam/pam_authd.so
test -e pam/go-exec/pam_authd_exec.so
rust-sanity:
name: "Rust: Code sanity"
runs-on: ubuntu-24.04 # ubuntu-latest-runner
steps:
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y ${{ env.apt_deps }} ${{ env.protobuf_compilers}}
- uses: actions/checkout@v4
- name: Rust code sanity check
uses: canonical/desktop-engineering/gh-actions/rust/code-sanity@main
with:
token: ${{ secrets.GITHUB_TOKEN }}
c-sanity:
name: "C Code sanity"
runs-on: ubuntu-24.04 # ubuntu-latest-runner
env:
CFLAGS: "-Werror"
steps:
- name: Install dependencies
run: |
set -eu
sudo apt update
sudo apt install -y ${{ env.apt_deps }} clang-tools clang
- name: Prepare report dir
run: |
set -eu
scan_build_dir=$(mktemp -d --tmpdir scan-build-dir-XXXXXX)
echo SCAN_BUILD_REPORTS_PATH="${scan_build_dir}" >> $GITHUB_ENV
- uses: actions/checkout@v4
- name: Run scan build on GDM extensions
run: |
set -eu
scan-build -v -o "${SCAN_BUILD_REPORTS_PATH}" clang ${CFLAGS} \
-Wno-gnu-variable-sized-type-not-at-end \
pam/internal/gdm/extension.h
- name: Run scan build on go-exec module
run: |
set -eu
scan-build -v -o "${SCAN_BUILD_REPORTS_PATH}" clang ${CFLAGS} \
-DAUTHD_TEST_MODULE=1 \
$(pkg-config --cflags --libs gio-unix-2.0 gio-2.0) \
-lpam -shared -fPIC \
pam/go-exec/module.c
- name: Upload scan build reports
uses: actions/upload-artifact@v4
with:
name: authd-${{ github.job }}-artifacts-${{ github.run_attempt }}
path: ${{ env.SCAN_BUILD_REPORTS_PATH }}
go-tests:
name: "Go: Tests"
runs-on: ubuntu-24.04 # ubuntu-latest-runner
strategy:
fail-fast: false
matrix:
test: ["coverage", "race", "asan"]
steps:
- name: Install dependencies
run: |
sudo apt update
# The integration tests build the NSS crate, so we need the cargo build dependencies in order to run them.
sudo apt install -y ${{ env.apt_deps }} ${{ env.protobuf_compilers}} ${{ env.test_apt_deps }}
- name: Install PAM and GLib debug symbols
run: |
set -eu
sudo apt-get install ubuntu-dbgsym-keyring -y
echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" | \
sudo tee -a /etc/apt/sources.list.d/ddebs.list
# Sometimes ddebs archive is stuck, so in case of failure we need to go manual
sudo apt update -y || true
if ! sudo apt install -y libpam-modules-dbgsym libpam0*-dbgsym libglib2.0-0*-dbgsym; then
sudo apt install -y ubuntu-dev-tools
pull-lp-ddebs pam $(lsb_release -cs)
pull-lp-ddebs glib2.0 $(lsb_release -cs)
sudo apt install -y ./libpam0*.ddeb ./libpam-modules*.ddeb ./libglib2.0-0*-dbgsym*.ddeb
sudo apt remove -y ubuntu-dev-tools
sudo apt autoremove -y
fi
- name: Install Chromium for VHS tests
# It's used by vhs, installing it once speeds up tests.
uses: browser-actions/setup-chrome@v1
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: go.mod
- name: Install gotestfmt and our wrapper script
uses: canonical/desktop-engineering/gh-actions/go/gotestfmt@main
- name: Install VHS and ttyd for integration tests
run: |
set -eu
go install github.com/charmbracelet/vhs@latest
# VHS requires ttyd >= 1.7.2 to work properly.
wget https://github.com/tsl0922/ttyd/releases/download/1.7.4/ttyd.x86_64
chmod +x ttyd.x86_64
sudo mv ttyd.x86_64 /usr/bin/ttyd
- name: Install rust
if: matrix.test != 'asan'
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly # We need nightly to enable instrumentation for coverage.
override: true
components: llvm-tools-preview
- name: Install grcov
if: matrix.test == 'coverage'
uses: baptiste0928/cargo-install@v3
with:
crate: grcov
- name: Prepare tests artifacts path
run: |
set -eu
artifacts_dir=$(mktemp -d --tmpdir authd-test-artifacts-XXXXXX)
echo AUTHD_TEST_ARTIFACTS_PATH="${artifacts_dir}" >> $GITHUB_ENV
echo ASAN_OPTIONS="log_path=${artifacts_dir}/asan.log:print_stats=true" >> $GITHUB_ENV
- name: Run tests (with coverage collection)
if: matrix.test == 'coverage'
env:
G_DEBUG: "fatal-criticals"
run: |
set -euo pipefail
# The coverage is not written if the output directory does not exist, so we need to create it.
cov_dir="$(pwd)/coverage"
cod_cov_dir="$(pwd)/coverage/codecov"
raw_cov_dir="${cov_dir}/raw"
mkdir -p "${raw_cov_dir}" "${cod_cov_dir}"
# Print executed commands to ease debugging
set -x
# Overriding the default coverage directory is not an exported flag of go test (yet), so
# we need to override it using the test.gocoverdir flag instead.
#TODO: Update when https://go-review.googlesource.com/c/go/+/456595 is merged.
go test -json -timeout ${GO_TESTS_TIMEOUT} -cover -covermode=set ./... -coverpkg=./... -shuffle=on -args -test.gocoverdir="${raw_cov_dir}" | \
gotestfmt --logfile "${AUTHD_TEST_ARTIFACTS_PATH}/gotestfmt.cover.log"
# Convert the raw coverage data into textfmt so we can merge the Rust one into it
go tool covdata textfmt -i="${raw_cov_dir}" -o="${cov_dir}/coverage.out"
# Append the Rust coverage data to the Go one
cat "${raw_cov_dir}/rust-cov/rust2go_coverage" >>"${cov_dir}/coverage.out"
# Filter out the testutils package and the pb.go file
grep -v -e "testutils" -e "pb.go" "${cov_dir}/coverage.out" >"${cod_cov_dir}/coverage.out.filtered"
# Move gcov output to coverage dir
mv "${raw_cov_dir}"/*.gcov "${cod_cov_dir}"
- name: Run tests (with race detector)
if: matrix.test == 'race'
env:
GO_TESTS_TIMEOUT: 35m
run: |
go test -json -timeout ${GO_TESTS_TIMEOUT} -race ./... | \
gotestfmt --logfile "${AUTHD_TEST_ARTIFACTS_PATH}/gotestfmt.race.log"
- name: Run PAM tests (with Address Sanitizer)
if: matrix.test == 'asan'
env:
# Do not optimize, keep debug symbols and frame pointer for better
# stack trace information in case of ASAN errors.
CGO_CFLAGS: "-O0 -g3 -fno-omit-frame-pointer"
G_DEBUG: "fatal-criticals"
GO_TESTS_TIMEOUT: 30m
# Use these flags to give ASAN a better time to unwind the stack trace
GO_GC_FLAGS: -N -l
run: |
# Print executed commands to ease debugging
set -x
go test -C ./pam/internal -json -asan -gcflags=all="${GO_GC_FLAGS}" -timeout ${GO_TESTS_TIMEOUT} ./... | \
gotestfmt --logfile "${AUTHD_TEST_ARTIFACTS_PATH}/gotestfmt.pam-internal-asan.log" || exit_code=$?
if [ -n "${exit_code:-}" ]; then
cat "${AUTHD_TEST_ARTIFACTS_PATH}"/asan.log* || true
exit ${exit_code}
fi
echo "Running PAM integration tests"
pushd ./pam/integration-tests
go test -asan -gcflags=all="${GO_GC_FLAGS}" -c
go tool test2json -p pam/integrations-test ./integration-tests.test \
-test.v=test2json \
-test.timeout ${GO_TESTS_TIMEOUT} | \
gotestfmt --logfile "${AUTHD_TEST_ARTIFACTS_PATH}/gotestfmt.pam-integration-tests-asan.log" || \
exit_code=$?
popd
# We don't need the xtrace output after this point
set +x
# We're logging to a file, and this is useful for having artifacts, but we still may want to see it in logs:
for f in "${AUTHD_TEST_ARTIFACTS_PATH}"/asan.log*; do
if ! [ -e "${f}" ]; then
continue
fi
if [ -s "${f}" ]; then
echo "::group::${f} ($(wc -l < "${f}") lines)"
cat "${f}"
echo "::endgroup::"
else
echo "${f}: empty"
fi
done
exit ${exit_code}
- name: Upload coverage to Codecov
if: matrix.test == 'coverage'
uses: codecov/codecov-action@v5
with:
directory: ./coverage/codecov
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test artifacts
uses: actions/upload-artifact@v4
with:
name: authd-${{ github.job }}-${{ matrix.test }}-artifacts-${{ github.run_attempt }}
path: ${{ env.AUTHD_TEST_ARTIFACTS_PATH }}