From 050dcdeb6718a4618ace5c13bf29bc04ba42f22b Mon Sep 17 00:00:00 2001 From: Mitchell Thompkins Date: Wed, 8 Jul 2026 21:14:33 +0000 Subject: [PATCH 1/2] ci: install from doc-free tarball instead of path hacking --- Makefile | 31 ++++++++++++++++++++---- devel/run_tests.m | 60 +++++------------------------------------------ 2 files changed, 33 insertions(+), 58 deletions(-) diff --git a/Makefile b/Makefile index b82e8029..47099e62 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,8 @@ DEPENDS := $(shell $(SED) -n -e 's/^[Dd]epends[^,]*, *\(.*\)/\1/p' $(DESCRIPTION TARGET_DIR := target RELEASE_DIR := $(TARGET_DIR)/$(PACKAGE)-$(VERSION) RELEASE_TARBALL := $(TARGET_DIR)/$(PACKAGE)-$(VERSION).tar.gz +RELEASE_DIR_CI := $(TARGET_DIR)/$(PACKAGE)-$(VERSION)-ci +RELEASE_TARBALL_CI := $(RELEASE_DIR_CI).tar.gz DOCS_HTML_DIR := docs DOCS_DIR := doc DOCS_DEV_DIR := devel/doc @@ -88,6 +90,8 @@ help: @echo " install - Install the package in GNU Octave" @echo " all - Build all oct files" @echo " check - Execute package tests (with install)" + @echo " check-ci - Build a doc-free tarball, install it, and run tests" + @echo " check-local - Run check-ci inside Docker via compose" @echo @echo " clean - Remove releases, doc and oct files" @echo " distclean - Remove releases, oct files and compiled libraries" @@ -135,6 +139,26 @@ $(RELEASE_DIR): .git/index @cd $@/$(SRC) && ./bootstrap && $(RM) -r "autom4te.cache" @chmod -R a+rX,u+w,go-w "$@" +$(RELEASE_DIR_CI): .git/index + @echo "Creating CI package dist directory $@ ..." + @-$(RM) -r $@ + @mkdir -p $@ + @echo " git archive ..." + @GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=safe.directory GIT_CONFIG_VALUE_0="$(abspath .)" \ + git archive -o $@/tmp.tar HEAD + @cd $@ && tar -xf tmp.tar && $(RM) tmp.tar + @echo " copy slicot files ..." + @mkdir -p $@/$(SC)/$(SC_LAPACK) + @cp -t $@/$(SC)/$(SC_SRC) $(SC_SUBMOD)/$(SC_SRC)/*.f + @cp -t $@/$(SC)/$(SC_LAPACK) $(SC_SUBMOD)/$(SC_LAPACK)/*.f + @cp $(SC_SUBMOD)/LICENSE $@/$(SC_SRC)/../ + @cp $(SC_SUBMOD)/README.md $@/$(SC_SRC)/../README-SLICOT.md + @cp $(SC_SUBMOD)/LICENSE $@/$(SC_DOC)/ + @cp $(SC_SUBMOD)/README.md $@/$(SC_DOC)/README-SLICOT.md + @echo " bootstrap ..." + @cd $@/$(SRC) && ./bootstrap && $(RM) -r "autom4te.cache" + @chmod -R a+rX,u+w,go-w "$@" + docs-html: @echo "Updating HTML documentation ... " @cd $(DOCS_HTML_DIR) && $(OCTAVE) \ @@ -208,11 +232,10 @@ check: install $(OCTAVE) --path "inst/" --path "src/" \ --eval 'pkg test control' -check-ci: - test -f $(SRC)/Makefile.conf || (cd $(SRC) && ./bootstrap && ./configure) - $(MAKE) -C $(SRC) all +check-ci: $(RELEASE_TARBALL_CI) $(OCTAVE) --no-gui --version - $(OCTAVE) --no-gui --path "inst/" --path "src/" devel/run_tests.m + $(OCTAVE) --no-gui --eval 'pkg install "$(RELEASE_TARBALL_CI)"' + $(OCTAVE) --no-gui devel/run_tests.m check-local: docker compose --file devel/compose.yaml --project-directory . run --rm octave diff --git a/devel/run_tests.m b/devel/run_tests.m index 79fae7c9..de774d4c 100644 --- a/devel/run_tests.m +++ b/devel/run_tests.m @@ -1,57 +1,9 @@ -## Run embedded %!test blocks from source without installing the package. -## -## The canonical way (according to the docs I've found) to to actually test is -## to call 'pkg test control' but that is coupled to docs today because it -## requires you to install first, but to install you have to build a release -## tarball with dist which depends on docs. This is a "hack" to get around that -## and just run the tests directly. This should probably change in the future -## b/c searching and grepping through a bunch of src files to test is very -## awkward. +## Run embedded %!test blocks from the installed control package. ## ## Called by 'make check-ci'. Exit code is nonzero if any tests fail. -## Register autoloads from PKG_ADD directives (normally done by pkg install) - -src_path = fullfile (fileparts (mfilename ("fullpath")), "..", "src"); - -## Find all .cc files in src/ b/c those are compiled to .oct files. We literally -## just want this out of the cpp files so that we know what .oct file we should -## target -## // PKG_ADD: autoload ("__sl_sb03md__", "__control_slicot_functions__.oct"); -cc_files = glob (fullfile (src_path, "*.cc")); - -## Read every file and grep of PKG_ADD, call autoload() on it with the absolute -## path to the .oct file. Autoload registers a deffered load which tells octave -## "when someone calls funcname, load filepath to find it, the .oct file isn't -## actually loaded until that first call" -for i = 1:numel (cc_files) - txt = fileread (cc_files{i}); - ## Use a regex to capture the 2 arguments (function name and .oct filename) - toks = regexp (txt, 'PKG_ADD: autoload \("(\w+)", "(\w+\.oct)"\)', "tokens"); - for j = 1:numel (toks) - autoload (toks{j}{1}, fullfile (src_path, toks{j}{2})); - endfor -endfor - -## Find all the class dirs to test ("inst", "inst/@tf", etc...) -dirs = [{"inst"}, cellstr(glob ("inst/@*"))']; - -n_pass = 0; -n_total = 0; - -## For every dir we collected, go through every mfile and call test -for i = 1:numel (dirs) - mfiles = dir (fullfile (dirs{i}, "*.m")); - for j = 1:numel (mfiles) - f = fullfile (mfiles(j).folder, mfiles(j).name); - ## collect output args from test call - ## https://docs.octave.org/v11.1.0/Test-Functions.html - [p, total, xfail, xbug, skip, rtskip] = test (f, "quiet", stdout); - n_pass += p; - n_total += total - xfail - xbug - skip - rtskip; - endfor -endfor - -n_fail = n_total - n_pass; -fprintf ("\nTotal: %d passed, %d failed\n", n_pass, n_fail); -exit (n_fail > 0); +pkg load control; +info = pkg ("list", "control"){1}; +dirs = [{info.dir}, cellstr(glob (fullfile (info.dir, "@*")))']; +[~, nfail] = __run_test_suite__ (dirs, {}); +exit (nfail > 0); From 7c7d2a9eb769bd16e47d3cca0702cef9f6c47d3d Mon Sep 17 00:00:00 2001 From: Mitchell Thompkins Date: Thu, 9 Jul 2026 20:47:04 +0000 Subject: [PATCH 2/2] add tarball-nodocs target --- Makefile | 7 +++++-- ci.md | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 ci.md diff --git a/Makefile b/Makefile index 47099e62..63416d69 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ DOCS_PDF := $(DOCS_DIR)/$(PACKAGE).pdf DOCS_QCH := $(DOCS_DIR)/$(PACKAGE).qch DOCS_LOGO := $(DOCS_DIR)/$(PACKAGE).svg -.PHONY: help dist docs-html docs release install all check check-ci check-local run clean +.PHONY: help dist docs-html docs release install all check check-ci check-local tarball-nodocs run clean help: @echo " " @@ -92,6 +92,7 @@ help: @echo " check - Execute package tests (with install)" @echo " check-ci - Build a doc-free tarball, install it, and run tests" @echo " check-local - Run check-ci inside Docker via compose" + @echo " tarball-nodocs - Build a doc-free tarball without running tests" @echo @echo " clean - Remove releases, doc and oct files" @echo " distclean - Remove releases, oct files and compiled libraries" @@ -232,7 +233,7 @@ check: install $(OCTAVE) --path "inst/" --path "src/" \ --eval 'pkg test control' -check-ci: $(RELEASE_TARBALL_CI) +check-ci: tarball-nodocs $(OCTAVE) --no-gui --version $(OCTAVE) --no-gui --eval 'pkg install "$(RELEASE_TARBALL_CI)"' $(OCTAVE) --no-gui devel/run_tests.m @@ -240,6 +241,8 @@ check-ci: $(RELEASE_TARBALL_CI) check-local: docker compose --file devel/compose.yaml --project-directory . run --rm octave +tarball-nodocs: $(RELEASE_TARBALL_CI) + clean: $(RM) -r $(TARGET_DIR) $(MAKE) -C $(SRC) clean diff --git a/ci.md b/ci.md new file mode 100644 index 00000000..b6a5e8f6 --- /dev/null +++ b/ci.md @@ -0,0 +1,26 @@ +# CI Notes + +## Why check-ci builds its own tarball + +The canonical way to test an Octave package is `pkg install` followed by +`pkg test`. Both require an installable tarball, which `make dist` normally +produces. + +`make dist` cannot run in the CI Docker image (`gnuoctave/octave`) because +the PDF documentation step fails. The `makeinfo --pdf` step invokes `pdfetex`, +which cannot include SVG images, and the manual references the project logo as +an SVG. No conversion toolchain (inkscape, rsvg-convert, etc.) is present in +the image. + +The `check-ci` target works around this by building a doc-free tarball via the +`RELEASE_DIR_CI` make target. That target mirrors `RELEASE_DIR` (used by +`make dist`) but omits the three lines that copy the PDF, QCH, and logo into +the package directory. + +## Git safe.directory in Docker + +The CI container runs as root while the bind-mounted source tree is owned by +the host user. Git 2.35.2 and later refuse to operate on repositories owned +by a different user. The `RELEASE_DIR_CI` recipe passes the trust exception +via environment variables (`GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_0`, +`GIT_CONFIG_VALUE_0`) so no global git config file is modified.