debug: demo the native-binary pre-check against the poisoned cache #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # THROWAWAY A/B experiment — DO NOT MERGE. | |
| # | |
| # Runs ONLY the "Test Codex session" smoke test on Linux, mirroring the real | |
| # `Linux / Electron-Smoke` job (github-hosted ubuntu-24.04) and restoring the | |
| # SAME shared `node_modules-linux-<hash>` cache the real job uses. | |
| # | |
| # A/B protocol: | |
| # Phase 1 (this commit, cachesalt unchanged): cache key is identical to the | |
| # failing PRs -> restores the SAME (suspected-poisoned) node_modules -> | |
| # expect the Codex smoke test to FAIL with "Codex binary not executable". | |
| # Phase 2 (bump build/.cachesalt in a follow-up commit): the cache key changes | |
| # -> cache MISS -> fresh `npm ci` reinstalls the codex native binary -> | |
| # expect the Codex smoke test to PASS. | |
| # | |
| # This job never SAVES the node_modules cache, so it cannot disturb the shared | |
| # caches. Delete this workflow after the experiment. | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: | |
| - codex-cache-debug | |
| permissions: {} | |
| jobs: | |
| codex-smoke: | |
| name: Codex smoke (Linux, single test) | |
| runs-on: ubuntu-24.04 | |
| env: | |
| NPM_ARCH: x64 | |
| VSCODE_ARCH: x64 | |
| steps: | |
| - name: Checkout microsoft/vscode | |
| uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: .nvmrc | |
| - name: Setup system services | |
| run: | | |
| set -e | |
| sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 | |
| ./build/azure-pipelines/linux/apt-retry.sh sudo apt-get update | |
| ./build/azure-pipelines/linux/apt-retry.sh sudo apt-get install -y pkg-config \ | |
| xvfb libgtk-3-0 libxkbfile-dev libkrb5-dev libgbm1 rpm bubblewrap socat | |
| sudo cp build/azure-pipelines/linux/xvfb.init /etc/init.d/xvfb | |
| sudo chmod +x /etc/init.d/xvfb | |
| sudo update-rc.d xvfb defaults | |
| sudo service xvfb start | |
| - name: Restore node_modules cache | |
| id: cache-node-modules | |
| uses: ./.github/actions/restore-node-modules | |
| with: | |
| key-prefix: node_modules-linux | |
| key-args: "linux ${{ env.VSCODE_ARCH }} $(node -p process.arch)" | |
| - name: Report cache hit/miss (the A/B signal) | |
| run: | | |
| echo "cache-hit = ${{ steps.cache-node-modules.outputs.cache-hit }}" | |
| echo "cache key = ${NODE_MODULES_CACHE_KEY:-<unset>}" | |
| echo "=== is the codex Linux binary present in the restored node_modules? ===" | |
| if [ -x node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex ]; then | |
| echo ">>> CODEX BINARY PRESENT" | |
| else | |
| echo ">>> CODEX BINARY MISSING (expected in Phase 1)" | |
| fi | |
| - name: Install build dependencies | |
| if: steps.cache-node-modules.outputs.cache-hit != 'true' | |
| working-directory: build | |
| run: | | |
| set -e | |
| for i in {1..5}; do | |
| npm ci && break | |
| if [ $i -eq 5 ]; then echo "Npm install failed too many times" >&2; exit 1; fi | |
| echo "Npm install failed $i, trying again..." | |
| done | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install dependencies | |
| if: steps.cache-node-modules.outputs.cache-hit != 'true' | |
| run: | | |
| set -e | |
| source ./build/azure-pipelines/linux/setup-env.sh | |
| for i in {1..5}; do | |
| npm ci && break | |
| if [ $i -eq 5 ]; then echo "Npm install failed too many times" >&2; exit 1; fi | |
| echo "Npm install failed $i, trying again..." | |
| done | |
| env: | |
| npm_config_arch: ${{ env.NPM_ARCH }} | |
| VSCODE_ARCH: ${{ env.VSCODE_ARCH }} | |
| ELECTRON_SKIP_BINARY_DOWNLOAD: 1 | |
| PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Re-check codex binary after any fresh install | |
| run: | | |
| if [ -x node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex ]; then | |
| echo ">>> POST-INSTALL: CODEX BINARY PRESENT" | |
| else | |
| echo ">>> POST-INSTALL: CODEX BINARY MISSING" | |
| fi | |
| - name: Create .build folder | |
| run: mkdir -p .build | |
| - name: Prepare built-in extensions cache key | |
| run: node build/azure-pipelines/common/computeBuiltInDepsCacheKey.ts > .build/builtindepshash | |
| - name: Restore built-in extensions cache | |
| id: cache-builtin-extensions | |
| uses: actions/cache/restore@v5 | |
| with: | |
| enableCrossOsArchive: true | |
| path: .build/builtInExtensions | |
| key: "builtin-extensions-${{ hashFiles('.build/builtindepshash') }}" | |
| - name: Download built-in extensions | |
| if: steps.cache-builtin-extensions.outputs.cache-hit != 'true' | |
| run: node build/lib/builtInExtensions.ts | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Workaround expat NULL deref CVEs in fontconfig parsing | |
| run: | | |
| set -e | |
| EXPAT_VER=$(dpkg-query -W -f='${Version}' libexpat1 2>/dev/null || echo "0") | |
| if dpkg --compare-versions "$EXPAT_VER" ge "2.7.5"; then | |
| exit 0 | |
| fi | |
| cat > /tmp/fonts-minimal.conf << 'FONTCONFIG_EOF' | |
| <?xml version="1.0"?> | |
| <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> | |
| <fontconfig> | |
| <dir>/usr/share/fonts</dir> | |
| <dir>/usr/local/share/fonts</dir> | |
| <dir prefix="xdg">fonts</dir> | |
| <cachedir>/var/cache/fontconfig</cachedir> | |
| <cachedir prefix="xdg">fontconfig</cachedir> | |
| <alias><family>monospace</family><prefer><family>DejaVu Sans Mono</family></prefer></alias> | |
| <alias><family>sans-serif</family><prefer><family>DejaVu Sans</family></prefer></alias> | |
| <alias><family>serif</family><prefer><family>DejaVu Serif</family></prefer></alias> | |
| <match target="pattern"> | |
| <test qual="all" name="family" compare="not_eq"><string>sans-serif</string></test> | |
| <test qual="all" name="family" compare="not_eq"><string>serif</string></test> | |
| <test qual="all" name="family" compare="not_eq"><string>monospace</string></test> | |
| <edit name="family" mode="append_last"><string>sans-serif</string></edit> | |
| </match> | |
| <config><rescan><int>0</int></rescan></config> | |
| </fontconfig> | |
| FONTCONFIG_EOF | |
| echo "FONTCONFIG_FILE=/tmp/fonts-minimal.conf" >> "$GITHUB_ENV" | |
| - name: Pre-initialize fontconfig to avoid Pango threaded FcInit crash | |
| run: | | |
| set -euo pipefail | |
| cat > "$RUNNER_TEMP/fcpreinit.c" <<'CEOF' | |
| #define _GNU_SOURCE | |
| #include <dlfcn.h> | |
| __attribute__((constructor)) | |
| static void preinit_fontconfig(void) | |
| { | |
| void *handle = dlopen("libfontconfig.so.1", RTLD_NOW | RTLD_GLOBAL); | |
| if (handle) { | |
| int (*fc_init)(void) = (int (*)(void)) dlsym(handle, "FcInit"); | |
| if (fc_init) { fc_init(); } | |
| } | |
| } | |
| CEOF | |
| gcc -shared -fPIC -O2 -o "$RUNNER_TEMP/libfcpreinit.so" "$RUNNER_TEMP/fcpreinit.c" -ldl | |
| echo "LD_PRELOAD=$RUNNER_TEMP/libfcpreinit.so${LD_PRELOAD:+:$LD_PRELOAD}" >> "$GITHUB_ENV" | |
| - name: Transpile client and extensions | |
| run: npm run gulp transpile-client-esbuild transpile-extensions | |
| - name: Download Electron and Playwright | |
| run: | | |
| set -e | |
| for i in {1..3}; do | |
| if npm exec -- npm-run-all2 -lp "electron ${{ env.VSCODE_ARCH }}" "playwright-install"; then | |
| echo "Download successful on attempt $i"; break | |
| fi | |
| if [ $i -eq 3 ]; then echo "Download failed after 3 attempts" >&2; exit 1; fi | |
| echo "Download failed on attempt $i, retrying..."; sleep 5 | |
| done | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compile extensions for smoke tests | |
| run: | | |
| set -e | |
| npm run gulp \ | |
| compile-extension:configuration-editing \ | |
| compile-extension:git \ | |
| compile-extension:github-authentication \ | |
| compile-extension:ipynb \ | |
| compile-extension:markdown-language-features \ | |
| compile-extension-media \ | |
| compile-extension:microsoft-authentication \ | |
| compile-extension:typescript-language-features | |
| - name: Compile smoke tests | |
| working-directory: test/smoke | |
| run: npm run compile | |
| - name: Compile Copilot Chat extension for smoke tests | |
| working-directory: extensions/copilot | |
| run: npm run compile | |
| - name: Remove musl Claude binary on glibc Linux | |
| run: rm -rf node_modules/@anthropic-ai/claude-agent-sdk-linux-x64-musl node_modules/@anthropic-ai/claude-agent-sdk-linux-arm64-musl | |
| - name: 🧪 Run ONLY the Codex smoke test (Electron) | |
| timeout-minutes: 15 | |
| run: npm run smoketest-no-compile -- --tracing -g "Test Codex session" | |
| env: | |
| DISPLAY: ":10" | |
| - name: Publish Log Files | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| continue-on-error: true | |
| with: | |
| name: codex-smoke-debug-logs-${{ github.run_attempt }} | |
| path: .build/logs | |
| if-no-files-found: ignore |