blob: 30b2045088e12345f3c8f82288a40c78723c74dd [file]
Variables
---------
The CI scripts use the following environment variables:
* APR_VERSION - if set, APR of this version is built and installed in
$HOME/root/apr-$APR_VERSION - a value of "trunk" means trunk is
used, "*.x" means a branch, otherwise a tagged version is implied.
* APR_CONFIG - arguments to pass when running APR's configure script
if APR_VERSION is set
* APU_VERSION - if set, APR-util of this version is built and
installed in $HOME/root/apr-util-$APU_VERSION - a value of "*.x"
means a branch, otherwise a tagged version is implied. (Since there
is no "trunk" for apr-util, that value cannot be used here.)
* APU_CONFIG - arguments to pass when running APR-util's configure
script if APU_VERSION is set
* CONFIG - arguments to pass to httpd's configure script.
* BUILDCONFIG - arguments to pass when running httpd's ./buildconf script
* MFLAGS - arguments to pass when running "make", both for httpd and
for any dependency built from source. The Linux workflow defaults
this to "-j<number of CPUs>"; a matrix entry can override it, e.g.
setting it empty to force a serial build.
* SKIP_TESTING - if set, no testing is done at all
* NO_TEST_FRAMEWORK - if set, the Perl-based test framework and
libcheck-based unit tests are skipped
* TEST_LOGNO - if set, checks for APLOGNO() macro errors (duplicates
or empty arguments) and exits; no build or testing is done.
* TEST_UBSAN - set for job using UBSan ("Undefined Behaviour Sanitizer")
* TEST_ASAN - set for job using ASan ("Address Sanitizer")
* TEST_MALLOC - set for job using enhanced malloc debugging
(sets MALLOC_PERTURB_, MALLOC_CHECK_ and LIBC_FATAL_STDERR_).
* TEST_INSTALL - set for job testing "make install"
* TEST_VPATH - set for job testing srcdir!=builddir (VPATH build)
* TEST_LDAP - set for job with slapd, running LDAP tests
* TEST_SSL - set for job with SSL/TLS testing variants (encrypted
private keys, session cache backends via redis/memcache/shmcb, etc.)
* TEST_OPENSSL3 - if set to a version string (e.g. "3.4.7"), that
version of OpenSSL is built from source and used for mod_ssl.
Requires non-system APR/APR-util (APR_VERSION must also be set).
* TEST_OPENSSL3_BRANCH - if set together with TEST_OPENSSL3, the
OpenSSL source is cloned from the named git branch instead of
downloading a release tarball.
* OPENSSL_CONFIG - extra arguments passed to OpenSSL's ./Configure
when building from source (e.g. "no-engine").
* TEST_PYTEST - if set, runs all available pytest-based test suites
via "make check-all-pytest" (pytest_suite/ and test/modules/*/
suites, in one pytest session). Replaces the old per-suite TEST_CORE
/ TEST_PROXY / TEST_H2 / TEST_MD flags. A suite whose dependencies
are missing skips itself: modules/md without `pebble` on PATH,
modules/http2 when mod_http2 was not built.
* PYTEST_ARGS - with TEST_PYTEST, test paths (relative to test/) and
options passed through to pytest, to narrow the run: "modules/http2",
"modules" (skip pytest_suite/), "pytest_suite/tests" (skip modules/),
"-k expr", "-m expr".
* TEST_NGHTTP2 - if set to a version string (e.g. "1.68.0"), that
release of nghttp2 is built from its GitHub tag (library only) and
used for mod_http2/mod_proxy_http2 via --with-nghttp2. Used by the
HTTP/2 workflow to test against nghttp2 versions other than the one
packaged for the runner image.
* TEST_MD - set together with TEST_PYTEST; installs pebble first so
that modules/md runs instead of skipping. See the
"Python pytest test suites" job in .github/workflows/linux.yml.
* TEST_APR_TARBALL - if set, APR/APR-util source is fetched as a
release tarball from archive.apache.org rather than cloned from git.
(This is necessary for old releases where running ./buildconf from
a tag may now be difficult.)
* TESTS - a list of Perl framework tests to run
* TEST_ARGS - arguments to pass to ./t/TEST in the Perl test framework
* LITMUS - if set, runs the litmus WebDAV test suite against mod_dav.
* PHP_FPM - path to the php-fpm binary. If set, PHP tests are
included in the pytest test suites. If not set by the matrix
entry, the workflow sets it to the newest /usr/sbin/php-fpm* found
in the runner image (e.g. "/usr/sbin/php-fpm8.3"), failing the job
if there is none.
Caching
-------
Two directories are cached.
~/root (key "cache-libs-<serial>-<image>-<arch>-$ROOTID") holds the
APR, APR-util and OpenSSL installs. gha-resolve-deps.sh computes
$ROOTID before the cache is restored, hashing only what determines
those installs: the versions, their configure arguments and $CC. The
job's own configuration is deliberately not included, so jobs building
the same dependencies share one entry however differently they
configure or test httpd - the five pool-debug jobs, for instance. A job
which builds no dependencies gets no $ROOTID and does not use the cache
at all.
For anything built from a branch rather than a tag - APR_VERSION=trunk
or 1.7.x, and TEST_OPENSSL3_BRANCH - the version alone does not identify
what gets built, so the branch is resolved to a commit and that goes
into $ROOTID too. The commit is exported as
$APR_COMMIT/$APU_COMMIT/$OPENSSL_COMMIT so that the build uses exactly
what the key names rather than resolving the branch a second time,
minutes later, by which point it may have moved.
It is restored before the dependencies are built and saved afterwards,
only if they built successfully - a failed job would otherwise write a
half-built tree to a key which can never be updated.
~/perl5 (key "cache-cpan-<serial>-$PERLID-<arch>-<hash>") holds the
CPAN modules. Nothing in it varies per job: the module list is fixed
and the modules are always built with CC=gcc, so the content depends
only on the perl ABI and on the module list itself, hashed from
travis_before_linux.sh. One cache is therefore shared by every job.
$PERLID is a hash of the "perl -V" output, computed by
gha-resolve-deps.sh, which also logs that output so a change to it can
be seen. The image name is deliberately not used: the runner image is
rebuilt regularly and its name does not change when perl does, so the
key outlived a perl upgrade which the modules did not. The key has no
restore-keys fallback, so the modules restored always match the perl
running the job.
The cached CPAN modules still become gradually stale as versions in
CPAN move on from whatever was installed for the first build. Bump
the serial in the key ("cache-cpan-1-" -> "cache-cpan-2-") to discard
them and rebuild against current CPAN.
APR and APR-util must stay in a single cache entry. APR-util's
buildconf needs APR's *source* tree, which lives in $HOME/build and is
not cached, so APR-util can only be built in a job which also builds
APR. $ROOTID covers both, and the entry is saved only once both have
built, so a restored entry never holds one without the other.
Artifacts
---------
A job which fails uploads its config.log, and the error_log from any
test run, as artifacts named "config.log-$JOBID" and "error_log-$JOBID".
$JOBID is the matrix index of the job followed by its name, with every
character upload-artifact rejects - "/" among them - replaced, so job
zero uploads "error_log-0-Shared-MPMs-event-pool-debug-SSL-TLS-variants".
The index is what makes the name unique. It cannot collide however the
matrix changes, including for an entry which sets no name at all,
whereas hashing a hand-picked subset of the job configuration - as this
used to do - collides silently as soon as two entries differ only in a
field which the hash omits. Two entries already differ only in "os",
which was never hashed: they stayed apart only because $ImageOS, which
was, happens to differ on an ARM runner. The job name is appended
purely so that an artifact can be matched to the job it came from
without counting matrix entries; it is not needed for uniqueness, and
an entry which sets none is still named unambiguously.
The name reaches the shell as $MATRIX_NAME through the step's env
rather than being interpolated into the script, so that no job name can
be written which breaks the shell.
The value computed for a job can be read from its log without waiting
for a failure: it is listed in the environment which the runner prints
under the "Run" group of every step after the one which sets it.
Travis to Github Actions Migration TODO
---------------------------------------
* test across different Ubuntu versions again
- and test against OpenSSL 1.x since we're now ONLY building against 3.x
* container testing for non-Ubuntu hosts
* introduce some job ordering rather than having a flat/concurrent
set, if the default "./configure && make && test" works *then* start
jobs doing 200 different variations on ./configure --enable-XXX
i.e. stop burning CPU time for a typo which breaks every job
TODO list
---------
* MacOS build
* clang-on-Linux build
* Use containers for non-Ubuntu-based Linux testing
Known Failures
--------------
- A few mod_http2 Python tests sometimes fail spuriously, e.g.
FAILED modules/http2/test_106_shutdown.py::TestShutdown::test_h2_106_02 - AssertionError: failed on 2. request: * Added test1.tests.httpd.apache.org:5001:127.0.0.1 to DNS cache
- mod_md tests can deadlock pebble v2.10.1 which hangs the test suite,
hopefully fixed for a future release. See e.g.
https://github.com/letsencrypt/pebble/pull/555
- ERROR at teardown of TestConf.test_md_300_022 - some race condition?
Testing from a Feature Branch
-----------------------------
An SVN branch off trunk should be mirrored to github, and will be
tested in the same way that trunk is in CI, so this workflow is
available for those familiar with using Subversion and the standard
ASF/httpd repository layout.
Test runs are listed at: https://github.com/apache/httpd/actions
A workflow to enable testing would be as follows, substituting
$USERNAME for your github username:
$ git clone https://github.com/apache/httpd
$ cd httpd
$ git remote add $USERNAME git@github.com:$USERNAME/httpd.git
$ git checkout -b my-feature origin/trunk
... do some work ...
$ git commit ...
$ git push -u $USERNAME my-feature:my-feature
To create a Pull Request, go to the URL produced in the "git push"
command output when pushing to your fork, which is something like:
https://github.com/apache/httpd/compare/trunk...$USERNAME:trunk
Once a PR has been created, the tests will run and test results
displayed directly in the PR.
To merge from github back to SVN trunk, create a patch from e.g.:
$ git diff origin/trunk..my-feature
and then apply it in SVN. To rebase a feature once trunk has
diverged, from a feature branch run:
$ git pull
$ git rebase -i origin/trunk
and follow the standard rebase steps.
An alternative way to apply a PR into an SVN checkout is to use the
apply_trunk_pr.sh script:
https://svn.apache.org/repos/asf/httpd/dev-tools/github/apply_trunk_pr.sh
If you use keywords in the SVN commit message, the PR will be closed
when the commit is mirrored to Github, e.g. a commit message like:
mod_foo: Fix the baz feature.
PR: 12345
Submitted by: Jane Doe <jane example.com>
GitHub: closes #1
will close PR #1 when it's merged.
2.4.x
-----
The 2.4.x workflow runs the pytest jobs of trunk's, and TEST_PYTEST and
"make check-all-pytest" work the same on both branches, so a test
backported from trunk needs no change in how it is run. A job that
configures an MPM which the branch does not have yet (MotorZ, for now)
succeeds without doing anything. travis_before_linux.sh and
travis_run_linux.sh are the same on both branches and do what the
workflow leaves to them:
* CLEAR_CACHE - if set, the cached $HOME/root and $HOME/perl5 are
removed before the build.
* MFLAGS - the 2.4.x workflow does not set it; the build script then
uses "-j2".
* TEST_MOD_TLS - with RUSTLS_VERSION, builds that tag of rustls-ffi
into $HOME/root/rustls and configures httpd with --with-tls and
--with-rustls.
When the workflow does not set $ROOTID, its cache key does not say what
was built, so the scripts check for themselves. APR and APR-util are
rebuilt unless $HOME/root/.key-apr (.key-apr-util) names the same
version, commit, configuration and $CC; OpenSSL is rebuilt unless
$HOME/root/openssl-is-$TEST_OPENSSL3 exists and, for a branch, names its
current commit; the CPAN modules are rebuilt when the output of
"perl -V" differs from the one saved in $HOME/perl5/.perlver.