krz/domain-dig
an ios app for DNS & SSL analysis
clone: git clone https://gitbay.org/krz/domain-dig.git
9201ef0008db5c45b33e75e674febe0cd4d4f0d5
verified · cmc
author: Christian Cleberg <hello@cleberg.net> · 2026-08-22T19:25:40Z
.github/workflows/build.yml | 127 -------------------------------------------- Docs/ACCESSIBILITY.txt | 30 +++++------ 2 files changed, 15 insertions(+), 142 deletions(-) deleted file mode 100644 @@ -1,127 +0,0 @@ -name: Build - -# Compile gate and accessibility audit for the GitHub mirror. builds.sr.ht is the -# primary remote for this project but has no macOS images, so xcodebuild cannot -# run there; this job builds and tests on a GitHub-hosted macOS runner instead. -# -# This runs `xcodebuild test`, which also compiles the app, the widget, and the -# share extension (the DomainDig scheme's build action pulls both in as -# dependencies). The scheme has two test targets: DomainDigUITests — an -# accessibility audit suite; see DomainDigUITests/AccessibilityAuditHarness.swift -# — and DomainDigTests — unit coverage of the deterministic core (report builder, -# exporter, diff, portability dedup). -# -# WHAT THIS JOB IS FOR, given the audit also runs locally: -# a clean checkout of the merge result. A local hook runs against the working -# tree and therefore cannot catch a file that was never committed — the failure -# mode that matters most here, since DomainDig.xcodeproj is hand-edited and uses -# file-system-synchronized groups where a whole missing folder still builds fine -# locally. This job is the only place that check exists; sr.ht cannot run it. -# -# DELIBERATELY ONE JOB, NEWEST RUNTIME ONLY. Audit coverage is not nested across -# OS versions, so the oldest supported OS genuinely needs its own run — but the -# macos-26 image ships only iOS 26.x runtimes, so CI *cannot* provide it. Asking -# for two jobs here bought two near-identical 26.x runs at double the macOS -# minutes. Floor coverage lives in Scripts/audit-a11y.sh, run from a machine that -# actually has an 18.x runtime installed, and is wired to the pre-push hook in -# .githooks/. See Docs/ACCESSIBILITY.md for the split. -# -# The audit REPORTS but does not FAIL by default. It surfaces violations that -# exist today, so gating on it would block every unrelated PR until the -# accessibility pass in issue #21 completes. Findings land in the job log and in -# the uploaded .xcresult bundle, tagged [report] or [FAIL]. Enforcement is a -# committed constant: widen `AccessibilityAuditHarness.enforcedAuditTypes` as -# each phase clears a category. (Env vars were tried first — neither a plain -# xcodebuild env var nor a TEST_RUNNER_-prefixed build setting reaches the UI -# test process.) -# -# pull_request only, plus manual dispatch. GitHub builds the merge result (PR -# merged into main), so a green PR validates exactly what will land on main. -# Note: this repo currently also pushes directly to main for releases, and those -# pushes are NOT gated here — add a `push: { branches: [main] }` trigger below if -# you want direct-to-main commits covered too. -# -# paths-ignore skips prose-only changes. Both globs are single-star, so they -# match the repo root and Docs/ but nothing deeper — a .md that ever lands inside -# a source directory still builds. -on: - pull_request: - paths-ignore: ['*.md', 'Docs/*.md'] - workflow_dispatch: - -# The job only reads code; drop the default read-write GITHUB_TOKEN scope. -permissions: - contents: read - -concurrency: - group: build-${{ github.ref }} - cancel-in-progress: true - -jobs: - test: - name: xcodebuild test - # macos-latest still points at macOS 15, which lacks the iOS 26+ SDK this app - # is built against. - runs-on: macos-26 - - steps: - - uses: actions/checkout@v7 - - - name: Show toolchain - run: | - xcodebuild -version - swift --version - - - name: Select simulator - id: sim - run: | - set -euo pipefail - - # Newest available iPhone runtime. No deployment-target filtering is - # needed for "newest" — it is always at or above the floor. The - # previous selector took the first iPhone from ANY runtime, which on a - # machine with an older runtime installed could pick a simulator below - # the deployment target, where the app cannot install. - selected=$(xcrun simctl list devices available --json \ - | jq -c ' - [ .devices | to_entries[] - | (.key | capture("SimRuntime\\.iOS-(?<maj>[0-9]+)-(?<min>[0-9]+)$")) as $v - | (($v.maj | tonumber) * 1000 + ($v.min | tonumber)) as $rank - | .value[] - | select(.name | startswith("iPhone")) - | { rank: $rank, udid: .udid, name: .name, os: "\($v.maj).\($v.min)" } - ] - | sort_by(.rank, .name) - | last - ') - - if [ -z "$selected" ] || [ "$selected" = "null" ]; then - echo "::error::No iPhone simulator available on this image" - xcrun simctl list devices available >&2 - exit 1 - fi - - label=$(echo "$selected" | jq -r '"\(.name) (iOS \(.os))"') - echo "Selected $label" - echo "udid=$(echo "$selected" | jq -r .udid)" >> "$GITHUB_OUTPUT" - echo "label=$label" >> "$GITHUB_OUTPUT" - - - name: Test on ${{ steps.sim.outputs.label }} - run: | - set -o pipefail - xcodebuild test \ - -project DomainDig.xcodeproj \ - -scheme DomainDig \ - -destination "id=${{ steps.sim.outputs.udid }}" \ - -resultBundlePath TestResults.xcresult \ - CODE_SIGNING_ALLOWED=NO - - - name: Upload results - # Always upload: on success the bundle carries the accessibility burndown - # list, which is the reason this suite exists. - if: always() - uses: actions/upload-artifact@v4 - with: - name: test-results - path: TestResults.xcresult - retention-days: 7 @@ -115,8 +115,8 @@ headers above. Everything the app actually controls passes in both schemes. With phases 1–5 landed, `AccessibilityAuditHarness.enforcedAuditTypes` enforces **`.textClipped`, `.dynamicType`, `.hitRegion`, `.elementDetection`, `.sufficientElementDescription`, `.trait`** on the empty-state test suite. A -named finding in any of these fails CI — regressions in five phases of work are -now gated, not merely reported. +named finding in any of these fails the test run — regressions in five phases of +work are still gated locally and at the pre-push hook, not merely reported. Three deliberate carve-outs, each with its evidence: @@ -143,7 +143,7 @@ Environment variables do not work: neither a plain `xcodebuild` env var nor a silently did nothing. And a committed value makes "when did clipping become enforced?" answerable with `git blame` instead of CI tribal knowledge. -## Why coverage is split between local and CI +## Why the floor runtime needs its own run **Audit coverage is not nested across OS versions.** Each runtime reports findings the others miss, in *both* directions. Measured on this project: @@ -158,18 +158,18 @@ Neither runtime is a superset, so the oldest supported OS needs its own run. This also rules out committing per-screen baseline counts as a regression guard: no single number is correct on both. -The catch is that **GitHub's `macos-26` image ships only iOS 26.x simulator -runtimes.** It cannot test the 17.6 floor at all. A two-job CI matrix was tried -and produced two near-identical 26.x runs at double the macOS minutes. - -So the work is split by what each side can uniquely do: - -| | Runtime | Uniquely provides | -| --- | --- | --- | -| **CI** (`.github/workflows/build.yml`) | newest available | A clean checkout of the merge result — catches a file that was never committed, which a local run cannot. Matters here because `DomainDig.xcodeproj` is hand-edited and uses file-system-synchronized groups, where a whole missing folder still builds locally. | -| **Local** (`Scripts/audit-a11y.sh`) | oldest supported + newest | Real floor coverage, on a machine that actually has an 18.x runtime installed. | - -Together they cover both ends; neither duplicates the other. +The audit therefore runs locally, across both ends, via +`Scripts/audit-a11y.sh` — on a machine that actually has an 18.x runtime +installed. It is wired to the pre-push hook in `.githooks/`. + +There is no CI job. The GitHub Actions workflow that used to run this suite on +the newest runtime has been removed, and with it the one check that no local run +can reproduce: **a clean checkout of the merge result.** That mattered here +because `DomainDig.xcodeproj` is hand-edited and uses file-system-synchronized +groups, where a whole missing folder still builds fine locally and breaks only +for someone else. A local hook runs against the working tree, so it cannot catch +a file that was never committed. Nothing covers that now — verify a fresh clone +by hand before a release. ## Running it