Backport envy-nx improvements: fixes, certs, tests, CI - #246
Merged
Conversation
- Get-LogLine: replace caller-scoped $ctx with $LogContext parameter (the function broke unless called from Show-LogContext's frame). - linux_setup.sh: pass -WarningAction SilentlyContinue to Invoke-GhRepoClone so $cloned doesn't capture warning text and fail the subsequent integer comparison. - upgrade_system.sh: quiet apt-get update/dist-upgrade with -qq. - ConvertTo-Cfg: widen $OrderedDict parameter type to System.Collections.IDictionary so hashtables and other dictionaries pipe in cleanly. - wsl_setup.ps1: read default-distro gh config via `cat ~/.config/gh/hosts.yml` instead of re-running setup_gh_https.sh with root on the default distro just to get its config back.
- Update-GitRepository: resolve upstream tracking ref in a single
`git rev-parse --abbrev-ref --symbolic-full-name @{upstream}`
instead of `git remote` + `git branch --show-current`. Add a
`git ls-remote --heads` pre-check so `git fetch --tags --prune
--prune-tags --force` is skipped when the remote tip already
matches the local tracking ref - cuts seconds off wsl_setup.ps1
startup on slow disks (fetch always rewrites FETCH_HEAD and
packed-refs even on no-op). 0/1/2 return contract preserved.
- Invoke-GhRepoClone: prefer SSH when a key is configured (probed
once via `ssh -T git@github.com`); fall back to HTTPS on SSH
clone failure with an explicit warning showing the URL and error.
Centralizes MITM proxy / private CA cert handling around a single
user-scope bundle at ~/.config/certs/ca-{custom,bundle}.crt that all
HTTP-aware tools can pick up via env vars - covers tools that ignore
the system CA store (Node.js, Python certifi, uv).
Producers (write to ~/.config/certs/):
- wsl/wsl_certs_add.ps1: after the existing system-store update,
also writes ca-custom.crt (PEM bundle of intercepted MITM proxy
certs only) and a ca-bundle.crt symlink to the system bundle.
- functions.sh: new `cert_intercept [host ...]` shell function pulls
the TLS chain from a host via openssl s_client, skips the leaf cert,
dedups against existing serials, appends intermediates/roots to
ca-custom.crt. Lets users capture proxy certs from inside the
distro without going via the Windows host.
Consumers:
- functions.sh: `fixcertpy` rewrite - prefers the user bundle when
present, falls back to system cert dirs; accepts explicit cacert.pem
paths as args; uses `find` instead of glob (zsh-safe); replaces
bash-4 assoc-array dedup with portable space-separated string;
Alpine no-op; clearer messages on permission failures.
- functions.sh: `sysinfo` zsh-compat fix - replaces mapfile + numeric
array indexing (0-based in bash, 1-based in zsh) with `read` so the
function works under zsh; sed `\s*` → `[[:space:]]*` for BSD sed.
- New .assets/config/bash_cfg/certs.sh: exports NODE_EXTRA_CA_CERTS
+ UV_SYSTEM_CERTS when ca-custom.crt exists, REQUESTS_CA_BUNDLE +
SSL_CERT_FILE when ca-bundle.crt exists.
- setup_profile_allusers.sh: installs certs.sh to /etc/profile.d/.
- setup_profile_user.{sh,zsh}: source /etc/profile.d/certs.sh from
~/.bashrc and ~/.zshrc.
- setup_profile_user.sh: also writes ~/.vscode-server/server-env-setup
so VS Code Server extensions see the cert env vars without sourcing
~/.bashrc (which the server doesn't do on launch).
Adds change-aware bats/Pester test infrastructure plus a static
zsh-compat lint, all backported from envy-nx and adapted to this
repo's module layout (InstallUtils/SetupUtils, bash_cfg/).
Pester (5 files, 42 tests) — coverage for parallel functions:
- GetLogLine.Tests.ps1 (SetupUtils/logs.ps1) — explicit assertion
that Get-LogLine works without $ctx in caller scope (the bug
fixed in PR A).
- ConvertCfg.Tests.ps1 (SetupUtils/common.ps1) — covers the
IDictionary parameter-type widening from PR A; sections,
comments, header preservation, hashtable input, roundtrip.
- ConvertPEM.Tests.ps1 (SetupUtils/certs.ps1) — covers the PEM
helpers used by the wsl_certs_add.ps1 cert-bundle write in PR C.
- InvokeCommandRetry.Tests.ps1 (InstallUtils/common.ps1).
- JoinStr.Tests.ps1 (InstallUtils/common.ps1).
Bats (2 files, 22 tests) — coverage for shell functions:
- test_functions.bats — sysinfo / fixcertpy / cert_intercept from
PR C: PEM bundle parsing, dedup logic, fall-back paths.
- test_fixcertpy_discovery.bats — focused tests for fixcertpy's
pip-show parsing patterns.
Hooks:
- run_pester.py — parses .Tests.ps1 dot-source lines to map source
→ tests, runs only the relevant tests for staged files.
- run_bats.py — same change-aware contract for bats.
- check_zsh_compat.py — flags bare `name() {`, numeric array
subscripts (1-based in zsh vs 0-based in bash), unquoted glob
for-loops (zsh nomatch abort), unguarded BASH_SOURCE / compgen /
COMP_WORDS. Inline `# zsh-ok` suppression. Wired to
.assets/config/bash_cfg/*.sh in pre-commit-config.
Pre-commit / Makefile:
- .pre-commit-config.yaml: adds bats-tests, pester-tests,
check-zsh-compat local hooks.
- Makefile: adds test / test-unit / test-bats / test-pester
targets.
Also fixes a Join-Str bug caught by the new tests:
- modules/InstallUtils/Functions/common.ps1: add
DefaultParameterSetName='None' so Join-Str works without
-SingleQuote/-DoubleQuote (matches the no-quote branch in the
function body, which was previously unreachable).
setup_profile_allusers.sh installs aliases_git.sh and functions.sh
into /etc/profile.d/. On Debian/Ubuntu /bin/sh is dash, and dash
sources /etc/profile.d/*.sh from /etc/profile when invoked as a
login shell - notably by the Determinate Nix installer's self-test
(`sh -lc <build>`). dash chokes on the bash `function` keyword:
sh: 2: /etc/profile.d/aliases_git.sh: function: not found
sh: 4: /etc/profile.d/aliases_git.sh: Syntax error: "}" unexpected
Surfaced when running envy-nx's nix/setup.sh inside a WSL distro
that this repo had previously provisioned.
Adds a POSIX-portable guard at the top of both files that no-ops
under dash but proceeds under bash and zsh:
[ -n "${BASH_VERSION:-}${ZSH_VERSION:-}" ] || return 0
Verified end-to-end with `dash -c '. <file>'` for all five files
in /etc/profile.d/ (aliases.sh, aliases_git.sh, aliases_kubectl.sh,
certs.sh, functions.sh) - all source cleanly. bash regression-check
confirms all eight functions still load. 42/42 Pester + 22/22 bats
still pass.
When WSL is set up with this repo and the user later runs scripts from /mnt/c/Users/<them>/source/repos/... (a common pattern when also using the repos from Windows), every git invocation surfaces: fatal: detected dubious ownership in repository at '/mnt/c/...' The .git dir's owner UID (Windows side) doesn't match the WSL user's UID, so git refuses to operate. Surfaced by envy-nx's nix/setup.sh self-test running git from /mnt/c/. Adds the per-user safe.directory entries during WSL provisioning in wsl_setup.ps1's GitHub setup region. Two globs cover the typical layouts: source/repos/<repo> and source/repos/<org>/<repo>. Writes to the WSL user's ~/.gitconfig (per-user, not system-wide), guarded with grep -qFx to stay idempotent on re-runs.
tests.yml (every PR + push to main, ~2 min):
Runs `make test` (bats + Pester) on ubuntu-latest. Catches module
regressions (logs.ps1, common.ps1, certs.ps1) and shell-helper
regressions (sysinfo, fixcertpy, cert_intercept) before merge.
Pester ships with the runner's pwsh; bats installed via apt.
test_linux.yml (label-gated, ~10 min):
Builds .assets/docker/Dockerfile end-to-end (which runs
linux_setup.sh) and runs four verification probes against the
resulting image:
- pwsh on PATH
- oh-my-posh on PATH
- /etc/profile.d/*.sh source cleanly under dash (regression
check for the POSIX-guard fix on aliases_git.sh / functions.sh)
- bash login shell exposes sysinfo / fixcertpy / cert_intercept /
git_current_branch / git_resolve_branch as functions
Triggers (matching envy-nx's test:integration pattern):
- workflow_dispatch (manual run from Actions tab)
- PR labeled with `test:integration`
- push to a PR that already has the `test:integration` label
Verification steps use continue-on-error and a final summary so a
single failure doesn't mask the rest of the picture.
BACKPORT.md is the playbook an agent (human or AI) follows when asked
to "backport recent envy-nx improvements." envy-nx is in rapid
(daily-ish) development; we deliberately don't rely on an upstream
marker on commits or CHANGELOG entries - every candidate is evaluated
at runtime against the rules in the doc.
Sections:
- Last ported through (the cut-off SHA/tag, bumped per backport PR)
- Procedure (9-step recipe from baseline through PR open)
- Eligibility rules (Port / Skip / Investigate buckets)
- Nix coupling signals (concrete patterns to grep for)
- Path mapping (envy-nx layout -> this repo's layout, with skip cells)
- Skip-list (paths that are never eligible)
- Hard rules (commit-level invariants)
- Module layout difference (vendored vs runtime-cloned ps-modules)
- Examples (5 concrete walkthroughs from the bootstrap PR:
pure copy, substantive port, surgical line fix, skip,
investigate-and-extract)
Also ports tests/hooks/align_tables.py from envy-nx (mechanical
markdown table column alignment, MD060 compliance) and wires it into
.pre-commit-config.yaml. Stdlib-only, ~130 lines. Idempotent on
already-aligned tables.
Upgrades tests/hooks/gremlins.py to envy-nx's auto-fixing version
(byte-identical): silently fixes dashes, smart quotes, fancy spaces,
ZWS/ZWJ, ellipsis, soft hyphens; exits non-zero only on truly
unfixable chars (currently just middle dot). Pre-commit's
modified-files detection blocks the commit so the user can review
the auto-fixes before re-staging.
Adds scop/pre-commit-shfmt v3.13.1-1 to .pre-commit-config.yaml,
matching envy-nx's config (excludes .zsh files, no extra args -
relies on .editorconfig's `indent_size = 2` for shell files).
Bulk-applied to the 6 tracked .sh files that had drift:
- .assets/provision/fix_gcloud_certs.sh: add missing `;;` before
`esac` on the opensuse case branch (latent bug that would have
caused fall-through into the next case if the case order ever
changed; shfmt caught it as a structural fix)
- .assets/provision/install_docker.sh: tighten `<<EOF >file`
spacing (cosmetic)
- .assets/provision/setup_gh_repos.sh: tighten `<<<"$x"` spacing
- .assets/provision/{setup_gh_ssh,setup_gnome,setup_ssh}.sh:
drop double blank lines after `set -euo pipefail`
Three additive Makefile improvements from envy-nx:
1. MITM proxy cert env in the prologue:
- PREK_NATIVE_TLS=1 tells prek to use OpenSSL's native CA store
(so it trusts the system trust anchors, including any custom
ones installed via wsl_certs_add.ps1)
- NODE_EXTRA_CA_CERTS is exported when ~/.config/certs/ca-custom.crt
exists, so prek-managed Node hooks (markdownlint-cli2, cspell)
work behind a MITM proxy
Pairs with the user-scope cert bundle added in PR C.
2. HOOK=id parameter on lint/lint-diff/lint-all:
make lint HOOK=shellcheck # run a single hook
Bare `make lint` still runs the full chain. lint-diff converted
to multi-line if/else so the conditional reads correctly with
the new $(HOOK) interpolation.
3. New `make hooks` target: lists hook IDs alphabetically by
parsing .pre-commit-config.yaml. Useful companion to HOOK=id
("which hooks can I single out?").
Skipped from envy-nx: `mkdocs-serve` (no docs site), `release`/
`egsave`/`test-nix` targets (no release pipeline / no nix tests),
the `uv run` prefix on prek (this repo doesn't have uv-managed
prek), the `hooks-install`/`hooks-remove` rename (would break the
existing `make install` / `make upgrade` contract).
editorconfig: include bats and bash extensions in the 2-space indent group so shfmt formats them correctly (matches envy-nx). Without this, shfmt fell back to its default tab indent on .bats files in lint-all. BACKPORT.md: bump "Last ported through" pointer to envy-nx 1.4.0 (commit c859bba, tagged v1.4.0, released 2026-05-01). The 1.4.0 release was reviewed against BACKPORT.md's eligibility rules - nothing new to port. The release is overwhelmingly nix-only work (manifest- driven nx CLI surface, four parity hooks defending it, nx_doctor refactor, nx.sh family-file split). The two parallel-functionality items (Update-GitRepository ls-remote pre-check, smarter check-zsh-compat BASH_SOURCE detection) are respectively already ported in PR B (b3a2b49) and not currently triggered by any wired file in this repo.
szymonos
force-pushed
the
chore/port-envy-nx-fixes-a
branch
from
May 1, 2026 20:32
247e751 to
ba8ddf1
Compare
This was referenced May 2, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Backports parallel-functionality improvements from
envy-nx(the cross-platform Nix descendant in rapid development) and lays down infrastructure to make future backports straightforward.safe.directorywiringBACKPORT.mdplaybook, shfmt + editorconfig + Makefile QoLCommits
76b7dfdb3a2b494ca536367c8cce58649cecf3ba30e126af8f53b87d84e98fcba21a57247e751Bug classes caught (by ports or by tests added in this PR)
Get-LogLine$ctx-leak (PR A) - new Pester test asserts it works without$ctxin caller scopeJoin-StrmissingDefaultParameterSetName- caught when running ported test against this repo's codefix_gcloud_certs.shmissing;;beforeesac- caught by shfmt/etc/profile.d/{aliases_git,functions}.shfailing under dash - caught bydash -c '. <file>'probe intest_linux.ymlValidation done locally
make lintandmake lint-allboth green (13 hooks)make testgreen: 22 bats + 42 Pesterdash -c '. <file>'clean for all 5/etc/profile.d/filesTest plan
Unit Testsworkflow passes (bats + Pester on every PR)Linux Integration Testpasses (Docker build + dash-source verification - fired bytest:integrationlabel, added below)Preflight Checkspasses (pre-commit hooks)wsl/wsl_setup.ps1 <distro>against an existing distro and verify:git config --global --get-all safe.directoryincludes/mnt/c/Users/.../source/repos/*patterns/etc/profile.d/{aliases_git,functions}.shsource cleanly underdash -c '. <file>'~/.config/certs/ca-custom.crtis populated when-AddCertificateflag was used; cert env vars present in user's bash login shell (echo \$NODE_EXTRA_CA_CERTS)~/source/repos/szymonos/envy-nx/nix/setup.shand confirm the Determinate Nix installer'ssh -lcself-test no longer fails onaliases_git.shparsingDocumented follow-ups (not in this PR)
Update-GitRepository/Invoke-GhRepoClone(commit 2 has no unit coverage)setup_profile_user.shcert env-var wiringwsl_setup.ps1and callwsl_certs_add.ps1automatically (Phase 2 - new functionality)Dockerfile.alpinetotest_linux.ymlmatrix for distro coveragevalidate_docs_words.py+ cspell hook for markdown spellcheck🤖 Generated with Claude Code