Skip to content

test(qa-gate): verify required-safe skip on a non-native PR (MCP-1219) #4

test(qa-gate): verify required-safe skip on a non-native PR (MCP-1219)

test(qa-gate): verify required-safe skip on a non-native PR (MCP-1219) #4

Workflow file for this run

# Native macOS tray test gate (MCP-1214).
#
# The macOS tray Settings form is a separate hand-port of the Web UI catalog,
# so web-only QA cannot catch native-only behavior bugs (validation, dirty
# detection, placeholders, bindings). This workflow makes that surface a
# first-class, deterministic merge gate:
#
# - swift-test : runs the native unit tests (GUI-free logic), which
# directly cover the spec-074 duration-field bugs.
# - settings-parity : fails when the web (fields.ts) and native
# (SettingsCatalog.swift) duration-field catalogs drift.
#
# Both job names are stable so they can be added to branch protection as
# required status checks. See docs/qa-merge-gate.md.
#
# REQUIRED-SAFE DESIGN (MCP-1219)
# -------------------------------
# These jobs are meant to be REQUIRED status checks on `main`. A required check
# that never produces a status blocks every PR that lacks it. GitHub produces
# NO status for a workflow skipped by a top-level `paths:` filter — the check
# stays "Expected — Waiting" forever and blocks the PR. So this workflow must
# trigger on EVERY pull request, then decide internally whether the real work
# runs:
#
# - No top-level `paths:` filter -> the workflow always runs.
# - The `changes` job detects whether native / settings files were touched.
# - swift-test / settings-parity are gated with a job-level `if:`. On a PR
# that touches none of those paths they are SKIPPED, and a skipped job
# reports its required context as satisfied (green) — unlike a skipped
# workflow, which reports nothing and blocks.
#
# Net effect: a native PR runs the real tests; a non-native PR (e.g. a deps
# bump) shows both contexts green without spending a macOS runner. Verify this
# on a non-native PR BEFORE adding the contexts to branch protection
# (docs/qa-merge-gate.md "Activation").
name: Native macOS Tests
on:
pull_request:
push:
branches: [main, next]
permissions:
contents: read
jobs:
changes:
name: detect-native-changes
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
native: ${{ steps.filter.outputs.native }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
native:
- 'native/macos/**'
- 'frontend/src/views/settings/**'
- 'frontend/src/components/settings/**'
- 'scripts/check-settings-parity.py'
- '.github/workflows/native-tests.yml'
swift-test:
name: swift-test
needs: changes
if: needs.changes.outputs.native == 'true'
runs-on: macos-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- name: Show Swift toolchain
run: swift --version
- name: Run native unit tests
working-directory: native/macos/MCPProxy
# NOTE: the skip-set below are pre-existing/environmental failures
# tracked for repair (AutoStart UserDefaults first-run, SSE-parser
# edge cases, a JSONEncoder behavior canary). They are unrelated to the
# tray form logic. Remove skips as each is fixed so coverage grows.
# Tracked in the native-test-suite-green follow-up.
run: |
swift test \
--skip AutoStartTests \
--skip testDefaultJSONEncoderDropsOptionalNilFromMap \
--skip testSSEEventDecodeInvalidDataThrows \
--skip testFieldWithColonButNoValue \
--skip testFieldWithNoColon
settings-parity:
name: settings-parity
needs: changes
if: needs.changes.outputs.native == 'true'
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Web <-> native settings catalog parity
run: python3 scripts/check-settings-parity.py