Trace native Linux GHC phases after CI build failure

This commit is contained in:
Moritz Angermann committed 2026-10-16 20:00:20 +09:00
1 parent 3e53def456
commit 58b736e73d
3 files changed
+68

No files matched your search

+28
View File
@@ -74,8 +74,36 @@ jobs:
# Use the compiler fork in flake.lock, including both Android ABIs.
# Stock GHC installed by ghcup is not interchangeable with this compiler.
- name: Build existing Haskell outputs
id: haskell_build
run: make nix-build
# Diagnose the same native library after failure. Keep the canonical
# failure and its flags intact; this is a separate diagnostic derivation.
- name: Trace native Linux GHC phases after failure
id: ghc_phase_trace
if: ${{ failure() && matrix.system == 'x86_64-linux' && steps.haskell_build.outcome == 'failure' }}
shell: bash
run: |
if [ -d "result-nix/$NIX_SYSTEM/lib:simplex-chat" ]; then
echo 'Native library already built; skipping its diagnostic trace.'
exit 0
fi
echo 'attempted=true' >> "$GITHUB_OUTPUT"
flake_ref="git+file://$GITHUB_WORKSPACE?rev=$(git rev-parse HEAD)"
original="(builtins.getFlake \"$flake_ref\").hydraJobs.x86_64-linux.\"lib:simplex-chat\""
timeout --kill-after=30s 7200s nice -n 10 nix build \
--file scripts/nix/trace-native-ghc.nix --arg original "$original" \
--no-link -L --keep-failed --max-jobs 1 --cores 1 --timeout 7200 \
2>&1 | tee native-linux-ghc-phase-trace.log
- name: Upload native Linux GHC phase log
if: ${{ always() && steps.ghc_phase_trace.outputs.attempted == 'true' }}
uses: actions/upload-artifact@v4
with:
name: nix-ghc-phase-trace-${{ github.sha }}
path: native-linux-ghc-phase-trace.log
if-no-files-found: warn
- name: Check native CLI encryption and profile passwords
run: python3 scripts/nix/smoke-cli.py "result-nix/$NIX_SYSTEM/exe:simplex-chat/bin/simplex-chat"
+10
View File
@@ -110,6 +110,16 @@ Darwin ARM64/x86_64, with a six-hour job limit. It uploads the existing library
and CLIs under an artifact named for the source SHA. Each native CLI also runs
the encrypted-store and profile-password smoke test, which can be repeated with
`python3 scripts/nix/smoke-cli.py result-nix/BUILD_SYSTEM/exe:simplex-chat/bin/simplex-chat`.
After a failed native x86_64 Linux library build, CI tries a separate derivation
with `-v2 -ddump-timings` on compile calls and uploads
`native-linux-ghc-phase-trace.log`, including when that trace fails. Compiler
queries and the original source, plan, dependency units and GHC arguments stay
unchanged. The canonical build remains failed. The trace has one job/core and a
two-hour wall-clock/per-derivation bound; the job's six-hour limit stays in place.
`trace-native-ghc.nix` accepts the original component via `--arg original` for the
same diagnostic locally.
Hydra continues to consume
the same `hydraJobs` attributes. The older application release workflow still
uses its existing GHCup/Docker compiler settings; migrating that packaging and
+30
View File
@@ -0,0 +1,30 @@
# Compile-phase diagnostics for an existing, already-planned native component.
# This produces a different derivation; it does not change source, plan, compiler,
# dependency units or the original GHC arguments. Query output stays unchanged.
{ original }:
let
needle = " printf '#!/bin/sh\\nexec %s \"$@\"\\n' \"$g\" > \"$wrapBin/$gName\"";
replacement = " printf '#!/bin/sh\\n"
+ "ghcTraceCompile=\\n"
+ "for arg do\\n"
+ " case \"$arg\" in\\n"
+ " --numeric-version|--version|-V|--info|--print-*|--show-*|--supported-*|--abi-hash|-M)\\n"
+ " exec \"%s\" \"$@\"\\n"
+ " ;;\\n"
+ " @*|--make|-c) ghcTraceCompile=1 ;;\\n"
+ " esac\\n"
+ "done\\n"
+ "if [ -n \"$ghcTraceCompile\" ]; then\\n"
+ " exec \"%s\" \"$@\" -v2 -ddump-timings\\n"
+ "fi\\n"
+ "exec \"%s\" \"$@\"\\n"
+ "' \"$g\" \"$g\" \"$g\" > \"$wrapBin/$gName\"";
occurrences = phase: builtins.div
(builtins.stringLength phase - builtins.stringLength
(builtins.replaceStrings [ needle ] [ "" ] phase))
(builtins.stringLength needle);
in original.overrideAttrs (old:
# Fail visibly if the pinned v2 builder changes its wrapper-generation seam.
assert occurrences old.buildPhase == 1; {
buildPhase = builtins.replaceStrings [ needle ] [ replacement ] old.buildPhase;
})