name: Smoke Test # Fast pre-flight build + make check across common-failure configs derived # from the Jenkins PRB top-10 (last 30 days). Intentionally runs on drafts # too: this is the gate that protects the rest of CI. Other PR workflows # wait for this via .github/actions/wait-for-smoke. # # The smoke config list lives in the "Build and make check" step below; # the generic runner .github/scripts/parallel-make-check.py builds each # config in its own out-of-tree ("VPATH") build directory off this single # checkout and runs make check across them on a pool of one-per-CPU worker # threads, reporting thread/CPU efficiency in the step summary. bubblewrap # is installed so the script tests re-exec themselves under bwrap # --unshare-net and concurrent checks cannot collide on TCP/UDP ports (do # not set AM_BWRAPPED here - that would disable it). Builds go through # ccache (cached across runs) to keep the single-runner job fast on warm # caches. # # For pull_request events the workflow tests the POST-MERGE tree: # the PR head is checked out, the base branch is merged in, and: # * a merge conflict fails the job before any build runs. # * if the PR tree is identical to base (no diff), the build is skipped. # * otherwise the build runs against the merged tree. # This catches stale PRs whose head builds clean but whose merge with # current master would break. on: push: branches: [ master, main ] paths-ignore: - '**/*.md' - 'doc/**' - 'AUTHORS' - 'LICENSING' - 'ChangeLog.md' pull_request: types: [opened, synchronize, reopened, ready_for_review] branches: [ master, main ] # Weekday-morning (10:00 UTC) build-only seed of the master-scoped ccache that PR runs restore # (in addition to the master pushes above). PR runs are read-only. schedule: - cron: '56 10 * * 1-5' concurrency: group: smoke-${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }} cancel-in-progress: true permissions: contents: read jobs: smoke: # Only run from the wolfssl org to avoid burning forks' CI minutes. if: github.repository_owner == 'wolfssl' runs-on: ubuntu-24.04 timeout-minutes: 60 env: CCACHE_MAXSIZE: 2G steps: # For PRs we explicitly check out the PR head (not the auto-merge # ref) and do the merge ourselves below so we can fail fast on # conflicts. For push events we just check out the pushed SHA. - uses: actions/checkout@v5 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Merge base into PR head (fail fast on conflict) id: merge_check if: github.event_name == 'pull_request' env: BASE_REF: ${{ github.event.pull_request.base.ref }} run: | set -e git config user.email "ci@wolfssl.invalid" git config user.name "wolfSSL CI Merge" git fetch --no-tags origin "$BASE_REF" BASE_SHA=$(git rev-parse FETCH_HEAD) if git diff --quiet "$BASE_SHA" HEAD; then echo "::notice::PR tree is identical to $BASE_REF; skipping smoke matrix." echo "skip=true" >> "$GITHUB_OUTPUT" exit 0 fi if ! git merge --no-ff --no-commit "$BASE_SHA"; then echo "::error::Merge conflicts with $BASE_REF - please rebase or merge $BASE_REF into the PR branch before testing." git merge --abort || true exit 1 fi echo "skip=false" >> "$GITHUB_OUTPUT" echo "Clean merge with $BASE_REF; testing post-merge tree." - name: Install dependencies if: steps.merge_check.outputs.skip != 'true' uses: ./.github/actions/install-apt-deps with: packages: autoconf automake libtool build-essential bubblewrap ccache ghcr-debs-tag: ubuntu-24.04-minimal # Ubuntu 24.04 can restrict unprivileged user namespaces via AppArmor, # which would stop the test scripts from re-execing under # bwrap --unshare-net (their port-isolation mechanism). - name: Allow unprivileged user namespaces (for bwrap) if: steps.merge_check.outputs.skip != 'true' run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 || true # ccache's default cache dir (XDG ~/.cache/ccache) is what the # actions/cache steps below restore/save; pin it explicitly so the two # cannot drift apart (e.g. if a later change sets CCACHE_DIR). - name: Pin ccache directory if: steps.merge_check.outputs.skip != 'true' run: echo "CCACHE_DIR=$HOME/.cache/ccache" >> "$GITHUB_ENV" # PRs restore the cache the master pushes / weekday seed write, but # never save it (the save step is gated to non-PR events below). - name: Restore ccache if: steps.merge_check.outputs.skip != 'true' uses: actions/cache/restore@v5 with: path: ~/.cache/ccache key: smoke-ccache-${{ github.base_ref || github.ref_name }}-${{ github.sha }} restore-keys: | smoke-ccache-${{ github.base_ref || github.ref_name }}- smoke-ccache- - name: autogen if: steps.merge_check.outputs.skip != 'true' run: | ccache -z ./autogen.sh # Common-failure configs derived from the Jenkins PRB top-10 (last 30 # days); leantls-extra, dtls-suite and integration target the top # failure modes (-Werror unused-function / implicit-decl / link # errors). Every config builds with -Werror unless it sets its own # cflags: sanitize-asan replaces it with AddressSanitizer flags (UBSAN # excluded - current master has known left-shift UB in auto-generated # SP math). --private-dir=certs gives every build dir its own certs/ # copy: crl-gen-openssl.test writes generated CRLs under certs/crl/, # which would race through the shared VPATH certs symlink. # # List order is schedule order: the worker threads take configs from # the top, so keep the slowest first or they straggle at the end on an # otherwise idle runner. Order by the Minutes column of the step # summary from a recent (warm-cache) run. - name: Build and make check all configs (parallel, out-of-tree) if: steps.merge_check.outputs.skip != 'true' run: | cat > "$RUNNER_TEMP/smoke-configs.json" <<'EOF' [ {"name": "sanitize-asan", "configure": ["--enable-all"], "cflags": "-fsanitize=address -fno-omit-frame-pointer -g -O1", "ldflags": "-fsanitize=address"}, {"name": "enable-all-smallstack", "configure": ["--enable-all", "--enable-smallstack"]}, {"name": "enable-all", "configure": ["--enable-all"]}, {"name": "integration", "configure": ["--enable-openssh", "--enable-lighty", "--enable-stunnel", "--enable-opensslextra"]}, {"name": "dtls-suite", "configure": ["--enable-psk", "--enable-dtls", "--enable-dtls13", "--enable-dtls-mtu", "--enable-aesccm", "--enable-opensslextra"]}, {"name": "opensslextra", "configure": ["--enable-opensslextra"]}, {"name": "default"}, {"name": "cryptonly", "configure": ["--enable-cryptonly"]}, {"name": "leantls-extra", "configure": ["--enable-leantls", "--enable-session-ticket", "--enable-sni", "--enable-opensslextra"]} ] EOF .github/scripts/parallel-make-check.py ${{ github.event_name == 'schedule' && '--build-only' || '' }} --cflags=-Werror \ --private-dir=certs "$RUNNER_TEMP/smoke-configs.json" # Seed (master pushes + the weekday cron) writes the master-scoped # ccache that PR runs restore; PRs never save. - name: Save ccache if: github.event_name != 'pull_request' && steps.merge_check.outputs.skip != 'true' uses: actions/cache/save@v5 with: path: ~/.cache/ccache key: smoke-ccache-${{ github.ref_name }}-${{ github.sha }} - name: ccache stats if: always() && steps.merge_check.outputs.skip != 'true' run: ccache -s || true - name: Upload logs on failure if: failure() && steps.merge_check.outputs.skip != 'true' uses: actions/upload-artifact@v6 with: retention-days: 7 name: smoke-logs path: | build-*/make-check.log build-*/test-suite.log build-*/config.log if-no-files-found: ignore