From 2320ede512a3dc3e8537cec2ef5ec53fc63bc878 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Aug 2026 13:05:36 +0200 Subject: [PATCH 1/4] Run hap and hapcryst's test suites in CI Both need polymaking and neither pins an upper bound, so what we do here reaches their released versions unchanged. Their suites are the only thing that tells us whether that still works, and running them by hand is what turned up that master, as it stands, breaks both: hapcryst fails outright and hap fails 26 of its tests, in each case on a global variable polymaking no longer sets. Install the package, check that it really did load this checkout rather than the polymaking shipped with GAP, and run whatever it declares as its TestFile. That check matters: without it the job would pass while testing nothing. hapcryst takes about 20 seconds and hap about a minute, so both are cheap enough to run on every pull request; there is also a nightly run, to catch breakage coming from their side. Co-Authored-By: Claude Opus 5 --- .github/workflows/downstream.yml | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/downstream.yml diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml new file mode 100644 index 0000000..e303e5d --- /dev/null +++ b/.github/workflows/downstream.yml @@ -0,0 +1,76 @@ +name: Downstream + +# hap and hapcryst both need polymaking, and neither pins an upper bound, so a +# change here reaches their released versions unchanged. Run their test suites +# against this checkout to find that out now rather than after a release. + +on: + push: + branches: + - master + - main + pull_request: + # they are slow, so also run nightly to catch breakage from their side + schedule: + - cron: '0 4 * * *' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref_name != github.event.repository.default_branch || github.run_number }} + cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} + +jobs: + downstream: + name: ${{ matrix.pkg }} + runs-on: ubuntu-latest + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + pkg: + - 'hapcryst' # drives polymaking hardest + - 'hap' + + steps: + - uses: actions/checkout@v6 + - uses: gap-actions/setup-gap@v3 + - uses: gap-actions/install-pkg@v1 + with: + packages: ${{ matrix.pkg }} + - uses: gap-actions/build-pkg@v3 + + # Without this the job could pass while testing against the polymaking + # that ships with GAP, which would tell us nothing. + - name: "Check that ${{ matrix.pkg }} loads this polymaking" + run: | + cat > check.g <<'EOF' + if LoadPackage("${{ matrix.pkg }}") = fail then + Print("FAILED to load ${{ matrix.pkg }}\n"); + FORCE_QUIT_GAP(1); + fi; + here := Filename(DirectoriesPackageLibrary("polymaking", "")[1], "");; + want := Concatenation(GAPInfo.SystemEnvironment.GITHUB_WORKSPACE, "/");; + Print("polymaking ", GAPInfo.PackagesInfo.polymaking[1].Version, + " loaded from ", here, "\n"); + if here <> want then + Print("expected the checkout at ", want, "\n"); + FORCE_QUIT_GAP(1); + fi; + FORCE_QUIT_GAP(0); + EOF + gap -A -q -b check.g + + - name: "Run ${{ matrix.pkg }}'s test suite" + run: | + cat > runtests.g <<'EOF' + # whatever the package itself considers its test suite + LoadPackage("${{ matrix.pkg }}");; + info := First(GAPInfo.PackagesInfo.("${{ matrix.pkg }}"), + r -> IsBound(r.TestFile));; + if info = fail then + Print("${{ matrix.pkg }} declares no TestFile\n"); + FORCE_QUIT_GAP(1); + fi; + Print("running ", info.TestFile, "\n"); + Read(Filename(Directory(info.InstallationPath), info.TestFile)); + EOF + gap -A -q -b runtests.g From 1044a5134234f2418f02c318e2b2d83d1be4b15f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Aug 2026 13:09:23 +0200 Subject: [PATCH 2/4] Install the packages hap and hapcryst need install-pkg installs what it is given and does not resolve dependencies, so both failed to load and the job never reached their tests. Name the whole closure, and print the package loading log if a load still fails, so the next such failure explains itself. Co-Authored-By: Claude Opus 5 --- .github/workflows/downstream.yml | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index e303e5d..ab1d177 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -26,16 +26,19 @@ jobs: strategy: fail-fast: false matrix: - pkg: - - 'hapcryst' # drives polymaking hardest - - 'hap' + include: + # install-pkg does not resolve dependencies, so name the whole closure + - pkg: 'hapcryst' # drives polymaking hardest + deps: 'hapcryst hap aclib cryst crystcat fga nq polycyclic smallgrp' + - pkg: 'hap' + deps: 'hap aclib crystcat fga nq polycyclic smallgrp' steps: - uses: actions/checkout@v6 - uses: gap-actions/setup-gap@v3 - uses: gap-actions/install-pkg@v1 with: - packages: ${{ matrix.pkg }} + packages: ${{ matrix.deps }} - uses: gap-actions/build-pkg@v3 # Without this the job could pass while testing against the polymaking @@ -44,7 +47,10 @@ jobs: run: | cat > check.g <<'EOF' if LoadPackage("${{ matrix.pkg }}") = fail then - Print("FAILED to load ${{ matrix.pkg }}\n"); + Print("FAILED to load ${{ matrix.pkg }}, loading log follows\n"); + SetInfoLevel(InfoPackageLoading, 4); + DisplayPackageLoadingLog(PACKAGE_DEBUG); + LoadPackage("${{ matrix.pkg }}");; FORCE_QUIT_GAP(1); fi; here := Filename(DirectoriesPackageLibrary("polymaking", "")[1], "");; From 31cf669f4f1926517d54d97b8a7c931260b023b5 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Aug 2026 13:12:26 +0200 Subject: [PATCH 3/4] Build the dependency packages, not just unpack them nq ships a program that has to be compiled, and hap will not load without it; install-pkg only unpacks. build-pkg takes an extra-pkgs list for packages that do not appear in our own PackageInfo.g. Co-Authored-By: Claude Opus 5 --- .github/workflows/downstream.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index ab1d177..3461787 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -39,7 +39,11 @@ jobs: - uses: gap-actions/install-pkg@v1 with: packages: ${{ matrix.deps }} + # nq and friends ship programs that have to be compiled; install-pkg only + # unpacks them, and they are not in our own PackageInfo.g - uses: gap-actions/build-pkg@v3 + with: + extra-pkgs: ${{ matrix.deps }} # Without this the job could pass while testing against the polymaking # that ships with GAP, which would tell us nothing. From 4d006024b770d9ce887eccc8b54caa5ac51be676 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 17 Aug 2026 13:15:02 +0200 Subject: [PATCH 4/4] Compare contents, not paths, when checking which polymaking loaded setup-gap stages the checkout under the GAP root rather than leaving it in GITHUB_WORKSPACE, so requiring the two paths to be equal rejected the very thing it was meant to accept. Compare PackageInfo.g instead, which works whether the checkout is copied or linked. The guard was worth having: it fired rather than letting both jobs pass while testing the polymaking that ships with GAP. Co-Authored-By: Claude Opus 5 --- .github/workflows/downstream.yml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml index 3461787..9b9c3a0 100644 --- a/.github/workflows/downstream.yml +++ b/.github/workflows/downstream.yml @@ -45,8 +45,9 @@ jobs: with: extra-pkgs: ${{ matrix.deps }} - # Without this the job could pass while testing against the polymaking - # that ships with GAP, which would tell us nothing. + # Without this the job could pass while testing the polymaking that ships + # with GAP, which would tell us nothing. setup-gap stages the checkout + # elsewhere than GITHUB_WORKSPACE, so compare contents rather than paths. - name: "Check that ${{ matrix.pkg }} loads this polymaking" run: | cat > check.g <<'EOF' @@ -57,17 +58,17 @@ jobs: LoadPackage("${{ matrix.pkg }}");; FORCE_QUIT_GAP(1); fi; - here := Filename(DirectoriesPackageLibrary("polymaking", "")[1], "");; - want := Concatenation(GAPInfo.SystemEnvironment.GITHUB_WORKSPACE, "/");; - Print("polymaking ", GAPInfo.PackagesInfo.polymaking[1].Version, - " loaded from ", here, "\n"); - if here <> want then - Print("expected the checkout at ", want, "\n"); - FORCE_QUIT_GAP(1); - fi; + PrintTo("loaded-from.txt", GAPInfo.PackagesInfo.polymaking[1].InstallationPath); FORCE_QUIT_GAP(0); EOF gap -A -q -b check.g + loaded=$(cat loaded-from.txt) + echo "polymaking loaded from ${loaded}" + if ! diff -q "${loaded}/PackageInfo.g" "${GITHUB_WORKSPACE}/PackageInfo.g" >/dev/null; then + echo "::error::${{ matrix.pkg }} loaded a different polymaking than the one under test" + exit 1 + fi + echo "matches the checkout" - name: "Run ${{ matrix.pkg }}'s test suite" run: |