e2e-tests: Retry invalid TOTP codes during Google login #4745
Workflow file for this run
This file contains hidden or 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: authd QA & sanity checks | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - '**' | |
| - '!.github/**' | |
| - '.github/workflows/qa.yaml' | |
| - '!.gitignore' | |
| - '!.gitmodules' | |
| - '!AGENTS.md' | |
| - '!CODE_OF_CONDUCT.md' | |
| - '!CONTRIBUTING.md' | |
| - '!COPYING' | |
| - '!COPYING.LESSER' | |
| - '!README.md' | |
| - '!SECURITY.md' | |
| - '!authd-oidc-brokers/**' | |
| - '!docs/**' | |
| - '!examplebroker/**' | |
| - '!gotestcov' | |
| - '!scripts/**' | |
| - '!snap/**' | |
| tags: | |
| - "*" | |
| pull_request: | |
| paths: | |
| - '**' | |
| - '!.github/**' | |
| - '.github/workflows/qa.yaml' | |
| - '!.gitignore' | |
| - '!.gitmodules' | |
| - '!AGENTS.md' | |
| - '!CODE_OF_CONDUCT.md' | |
| - '!CONTRIBUTING.md' | |
| - '!COPYING' | |
| - '!COPYING.LESSER' | |
| - '!README.md' | |
| - '!SECURITY.md' | |
| - '!authd-oidc-brokers/**' | |
| - '!docs/**' | |
| - '!examplebroker/**' | |
| - '!gotestcov' | |
| - '!scripts/**' | |
| - '!snap/**' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| DEBIAN_FRONTEND: noninteractive | |
| GO_TESTS_TIMEOUT: 20m | |
| AUTHD_SSHD_STDERR_LOG_ALL_PAM_MESSAGES: true | |
| c_build_dependencies: >- | |
| clang-tools | |
| clang | |
| libglib2.0-dev | |
| libpam-dev | |
| go_build_dependencies: >- | |
| libglib2.0-dev | |
| libpam-dev | |
| libpwquality-dev | |
| go_test_dependencies: >- | |
| bubblewrap | |
| cracklib-runtime | |
| git-delta | |
| openssh-client | |
| openssh-server | |
| jobs: | |
| go-sanity: | |
| name: "Go: Code sanity" | |
| permissions: {} | |
| runs-on: ubuntu-24.04 # ubuntu-latest-runner | |
| steps: | |
| - uses: canonical/desktop-engineering/gh-actions/common/dpkg-install-speedup@main | |
| - name: Install dependencies | |
| run: | | |
| # Install dependencies | |
| set -eu | |
| sudo apt-get update | |
| sudo apt-get install -y ${{ env.go_build_dependencies }} | |
| - uses: actions/checkout@v6 | |
| - name: Go code sanity check | |
| uses: canonical/desktop-engineering/gh-actions/go/code-sanity@v2 | |
| with: | |
| golangci-lint-configfile: ".golangci.yaml" | |
| tools-directory: "tools" | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - 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 | |
| shell-sanity: | |
| name: "Shell: Code sanity" | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Run ShellCheck | |
| uses: ludeeus/action-shellcheck@master | |
| with: | |
| ignore_paths: "./authd-oidc-brokers" | |
| rust-sanity: | |
| name: "Rust: Code sanity" | |
| permissions: {} | |
| runs-on: ubuntu-24.04 # ubuntu-latest-runner | |
| steps: | |
| - uses: canonical/desktop-engineering/gh-actions/common/dpkg-install-speedup@main | |
| - name: Install dependencies | |
| run: | | |
| # Install dependencies | |
| set -eu | |
| sudo apt-get update | |
| # In Rust the grpc stubs are generated at build time | |
| # so we always need to install the protobuf compilers | |
| # when building the NSS crate. | |
| sudo apt-get install -y protobuf-compiler | |
| - uses: actions/checkout@v6 | |
| - 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: | |
| - uses: canonical/desktop-engineering/gh-actions/common/dpkg-install-speedup@main | |
| - name: Install dependencies | |
| run: | | |
| # Install dependencies | |
| set -eu | |
| sudo apt-get update | |
| sudo apt-get install -y ${{ env.c_build_dependencies }} | |
| - 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@v6 | |
| - 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@v7 | |
| with: | |
| name: authd-${{ github.job }}-artifacts-${{ github.run_attempt }} | |
| path: ${{ env.SCAN_BUILD_REPORTS_PATH }} | |
| go-tests-coverage: | |
| name: "Go Tests with Coverage Collection" | |
| runs-on: ubuntu-24.04 # ubuntu-latest-runner | |
| env: | |
| RAW_COVERAGE_DIR: ${{ github.workspace }}/raw-coverage | |
| COVERAGE_DIR: ${{ github.workspace }}/coverage | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/setup-go-tests | |
| - uses: ./.github/actions/setup-go-coverage-tests | |
| # Installation of debug symbols takes a long time (and fails currently), | |
| # so we skip it for now. Enable on demand. | |
| # - uses: ./.github/actions/install-debug-symbols | |
| # continue-on-error: true | |
| - name: Run tests with coverage collection | |
| 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. | |
| mkdir -p "${RAW_COVERAGE_DIR}" | |
| # Print executed commands to ease debugging | |
| set -x | |
| # Work around https://github.com/golang/go/issues/75031 | |
| go env -w GOTOOLCHAIN="$(go version | awk '{ print $3 }')+auto" | |
| # 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_COVERAGE_DIR}" | \ | |
| gotestfmt --logfile "${AUTHD_TESTS_ARTIFACTS_PATH}/gotestfmt.cover.log" | |
| # Upload the test output for the go-tests-coverage-retry job which retries | |
| # the failed tests. | |
| - name: Upload JSON test output on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-test-output | |
| path: ${{ env.AUTHD_TESTS_ARTIFACTS_PATH }}/gotestfmt.cover.stdout | |
| # Upload the raw coverage data so that the go-tests-coverage-retry job has | |
| # all the data to generate the coverage report (if the tests succeed on | |
| # retry). | |
| - name: Upload raw coverage on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: raw-coverage-data | |
| path: ${{ env.RAW_COVERAGE_DIR }} | |
| - uses: ./.github/actions/generate-coverage-report | |
| with: | |
| codecov-token: ${{ secrets.CODECOV_TOKEN }} | |
| - uses: ./.github/actions/upload-test-artifacts | |
| if: always() | |
| go-tests-coverage-retry: | |
| name: "Retry Go Tests with Coverage Collection" | |
| needs: go-tests-coverage | |
| if: always() && needs.go-tests-coverage.result == 'failure' | |
| runs-on: ubuntu-24.04 | |
| env: | |
| RAW_COVERAGE_DIR: ${{ github.workspace }}/raw-coverage | |
| COVERAGE_DIR: ${{ github.workspace }}/coverage | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/setup-go-tests | |
| - uses: ./.github/actions/setup-go-coverage-tests | |
| # Installation of debug symbols takes a long time (and fails currently), | |
| # so we skip it for now. Enable on demand. | |
| # - uses: ./.github/actions/install-debug-symbols | |
| # continue-on-error: true | |
| - name: Download JSON output of failed tests | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: coverage-test-output | |
| path: /tmp/coverage-test-output | |
| - name: Download raw coverage data | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: raw-coverage-data | |
| path: ${{ env.RAW_COVERAGE_DIR }} | |
| - name: Install gotest-rerun-failed | |
| run: go install github.com/adombeck/gotest-rerun-failed@latest | |
| - name: Retry failed tests with coverage collection | |
| run: | | |
| set -euo pipefail | |
| # Print executed commands to ease debugging | |
| set -x | |
| test_output="/tmp/coverage-test-output/gotestfmt.cover.stdout" | |
| for i in $(seq 1 3); do | |
| echo "Retrying failed tests (attempt ${i})" | |
| gotest-rerun-failed -json -timeout ${GO_TESTS_TIMEOUT} -cover -covermode=set -- -coverpkg=./... \ | |
| -shuffle=on -args -test.gocoverdir="${RAW_COVERAGE_DIR}" \ | |
| < "${test_output}" \ | |
| | gotestfmt --logfile "${AUTHD_TESTS_ARTIFACTS_PATH}/gotestfmt.cover.retry-$i.log" \ | |
| && exit_code=0 || exit_code=$? | |
| if [ "${exit_code}" -eq 0 ]; then | |
| break | |
| fi | |
| if [ "${i}" -eq 3 ]; then | |
| echo "Tests failed 3 times, giving up" | |
| exit ${exit_code} | |
| fi | |
| test_output="${AUTHD_TESTS_ARTIFACTS_PATH}/gotestfmt.cover.retry-$i.stdout" | |
| done | |
| - uses: ./.github/actions/generate-coverage-report | |
| with: | |
| codecov-token: ${{ secrets.CODECOV_TOKEN }} | |
| - uses: ./.github/actions/upload-test-artifacts | |
| if: always() | |
| go-tests-race: | |
| name: "Go Tests with Race Detector" | |
| runs-on: ubuntu-24.04 # ubuntu-latest-runner | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/setup-go-tests | |
| # Installation of debug symbols takes a long time (and fails currently), | |
| # so we skip it for now. Enable on demand. | |
| # - uses: ./.github/actions/install-debug-symbols | |
| # continue-on-error: true | |
| - name: Run tests with race detector | |
| env: | |
| GO_TESTS_TIMEOUT: 35m | |
| AUTHD_TESTS_SLEEP_MULTIPLIER: 3 | |
| AUTHD_SKIP_FLAKY_TESTS: true | |
| GORACE: log_path=${{ env.AUTHD_TESTS_ARTIFACTS_PATH }}/gorace.log | |
| run: | | |
| go test -json -timeout ${GO_TESTS_TIMEOUT} -race -failfast ./... | \ | |
| gotestfmt --logfile "${AUTHD_TESTS_ARTIFACTS_PATH}/gotestfmt.race.log" || exit_code=$? | |
| if [ "${exit_code:-0}" -ne 0 ]; then | |
| cat "${AUTHD_TESTS_ARTIFACTS_PATH}"/gorace.log* || true | |
| exit ${exit_code} | |
| fi | |
| - uses: ./.github/actions/upload-test-artifacts | |
| if: always() | |
| go-tests-asan: | |
| name: "Go PAM tests with Address Sanitizer" | |
| runs-on: ubuntu-24.04 # ubuntu-latest-runner | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: ./.github/actions/setup-go-tests | |
| # Installation of debug symbols takes a long time (and fails currently), | |
| # so we skip it for now. Enable on demand. | |
| # - uses: ./.github/actions/install-debug-symbols | |
| # continue-on-error: true | |
| - name: Run PAM tests with Address Sanitizer | |
| 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 | |
| AUTHD_TESTS_SLEEP_MULTIPLIER: 1.5 | |
| AUTHD_SKIP_FLAKY_TESTS: true | |
| # 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 | |
| echo "::group::Install llvm-symbolizer" | |
| # For llvm-symbolizer | |
| sudo apt-get install -y llvm | |
| echo "::endgroup::" | |
| go test -C ./pam/internal -json -asan -gcflags=all="${GO_GC_FLAGS}" -failfast -timeout ${GO_TESTS_TIMEOUT} ./... | \ | |
| gotestfmt --logfile "${AUTHD_TESTS_ARTIFACTS_PATH}/gotestfmt.pam-internal-asan.log" || exit_code=$? | |
| if [ -n "${exit_code:-}" ]; then | |
| cat "${AUTHD_TESTS_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.failfast \ | |
| -test.timeout ${GO_TESTS_TIMEOUT} | \ | |
| gotestfmt --logfile "${AUTHD_TESTS_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_TESTS_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} | |
| - uses: ./.github/actions/upload-test-artifacts | |
| if: always() |