Skip to content

Commit 0baea41

Browse files
committed
chore(gates): resolve shallow PR impact and iOS screenshot coverage
1 parent a19fd96 commit 0baea41

4 files changed

Lines changed: 51 additions & 13 deletions

File tree

‎apple/runner/AgentDeviceRunner/AgentDeviceRunnerUITests/UnitTests/RunnerTests+LifecycleTests.swift‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ extension RunnerTests {
9797
// into the runner's temporary directory.
9898
let fileName = URL(fileURLWithPath: message).lastPathComponent
9999
XCTAssertTrue(message.hasSuffix(fileName), message)
100+
#if os(iOS)
101+
XCTAssertTrue(message.hasPrefix("tmp/"), message)
102+
#elseif os(macOS)
103+
XCTAssertTrue(message.hasPrefix("/"), message)
104+
#endif
100105
let storedPath = (NSTemporaryDirectory() as NSString).appendingPathComponent(fileName)
101106
XCTAssertEqual(try Data(contentsOf: URL(fileURLWithPath: storedPath)), pngData)
102107
XCTAssertEqual(response.data?.screenshotMetadata?.pixelsPerPoint, 3)

‎scripts/__tests__/apple-ci-impact.test.ts‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import fs from 'node:fs';
2+
import { execFileSync } from 'node:child_process';
3+
import os from 'node:os';
24
import path from 'node:path';
35
import { expect, test } from 'vitest';
46
import { parse } from 'yaml';
@@ -112,3 +114,43 @@ test('bridge proof runs for its owning sources and uncertain tooling changes', (
112114
expect(selectAppleBridgeProof(null).run).toBe(true);
113115
expect(selectAppleBridgeProof([]).run).toBe(true);
114116
});
117+
118+
test('a shallow PR merge still yields a known change set for both selectors', () => {
119+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'apple-ci-impact-'));
120+
const source = path.join(root, 'source');
121+
const shallow = path.join(root, 'shallow');
122+
fs.mkdirSync(source);
123+
const git = (cwd: string, ...args: string[]) =>
124+
execFileSync('git', args, { cwd, encoding: 'utf8' }).trim();
125+
try {
126+
git(source, 'init', '-q', '-b', 'main');
127+
git(source, 'config', 'user.email', '[email protected]');
128+
git(source, 'config', 'user.name', 'Test');
129+
git(source, 'commit', '--allow-empty', '-qm', 'base');
130+
const base = git(source, 'rev-parse', 'HEAD');
131+
git(source, 'checkout', '-qb', 'feature');
132+
fs.mkdirSync(path.join(source, 'src'));
133+
fs.writeFileSync(path.join(source, 'src', 'feature.ts'), 'export const feature = true;\n');
134+
git(source, 'add', '.');
135+
git(source, 'commit', '-qm', 'feature');
136+
git(source, 'checkout', '-q', 'main');
137+
git(source, 'merge', '-q', '--no-ff', '-m', 'merge', 'feature');
138+
git(root, 'clone', '-q', '--depth=1', '--branch', 'main', `file://${source}`, shallow);
139+
git(shallow, 'fetch', '-q', 'origin', base, '--depth=1');
140+
expect(git(shallow, 'rev-parse', '--is-shallow-repository')).toBe('true');
141+
const select = (target: string) =>
142+
execFileSync(
143+
process.execPath,
144+
['--experimental-strip-types', path.join(repoRoot, 'scripts/apple-ci-impact.ts'), target],
145+
{
146+
cwd: shallow,
147+
encoding: 'utf8',
148+
env: { ...process.env, BASE_SHA: base, GITHUB_EVENT_NAME: 'pull_request' },
149+
},
150+
);
151+
expect(select('xctest')).toContain('skip;');
152+
expect(select('bridge')).toContain('skip;');
153+
} finally {
154+
fs.rmSync(root, { recursive: true, force: true });
155+
}
156+
});

‎scripts/apple-ci-impact.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function selectAppleBridgeProof(changedPaths: readonly string[] | null):
5353

5454
function changedPathsFromGit(baseSha: string): string[] | null {
5555
if (!/^[a-f0-9]{40}$/.test(baseSha)) return null;
56-
const result = spawnSync('git', ['diff', '--name-only', '-z', `${baseSha}...HEAD`], {
56+
const result = spawnSync('git', ['diff', '--name-only', '-z', baseSha, 'HEAD'], {
5757
encoding: 'utf8',
5858
});
5959
if (result.error || result.status !== 0 || result.stdout === null) return null;

‎scripts/check-xctest-selection.ts‎

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@
88
// - host macos.yml, macOS host, every PR: the whole bundle as compiled for macOS, minus
99
// `-skip-testing:` — the pure runner-decision tests, whose guard is
1010
// `#if AGENT_DEVICE_RUNNER_UNIT_TESTS` alone.
11-
// - pr ios.yml, iOS Simulator, when runner inputs change on a PR (and on every main
12-
// push): methods compiled only for iOS, plus shared methods with platform-
13-
// dependent bodies, derived from Swift guards.
11+
// - pr ios.yml, iOS Simulator: tests with iOS-specific Swift bodies, when selected.
1412
// - nightly xctest-nightly.yml, iOS Simulator, scheduled: the whole bundle as compiled for
1513
// iOS, minus `-skip-testing:` — includes the simulator-only tests, whose guard is
1614
// `… && os(iOS)` (they launch the host app, route through SpringBoard, or assert an
@@ -20,10 +18,8 @@
2018
// platform rather than treating a source-level `func test…` as running everywhere. What it
2119
// holds:
2220
//
23-
// 1. Every `-skip-testing:` identifier names a declared method that compiles for its lane,
24-
// and the PR workflow consumes the generated list. `xcodebuild` treats a skip identifier
25-
// matching nothing as an empty set, which re-admits `RunnerTests/testCommand` — not a test
26-
// but the runner's server entry point, which opens an NWListener and waits 24 hours.
21+
// 1. Every `-skip-testing:` identifier compiles for its lane. An unknown skip re-admits
22+
// `RunnerTests/testCommand`, the server entry point that waits 24 hours.
2723
// 2. Every declared method is reachable by at least one lane. A test gated to a platform
2824
// no lane runs (the tvOS-only pair this check found) is dark from the day it is written.
2925
// 3. The entry point is reachable by no lane at all.
@@ -51,7 +47,6 @@ const packageAppleRunnerScript = path.join(repoRoot, 'scripts/package-apple-runn
5147
/** The macOS host lane, which runs the whole macOS-compiled bundle on every PR. */
5248
export const HOST_WORKFLOW_FILE = '.github/workflows/macos.yml';
5349

54-
/** The PR lane, whose generated iOS-specific list runs on selected pull requests. */
5550
export const PR_WORKFLOW_FILE = '.github/workflows/ios.yml';
5651

5752
/** The nightly lane, whose `-skip-testing:` list decides what the full simulator suite leaves out. */
@@ -158,11 +153,8 @@ export type SelectionReport = {
158153
readonly dark: readonly string[];
159154
/** Lanes that reach the entry point — a failure (a 24-hour hang). */
160155
readonly entryPointReachedBy: readonly LaneId[];
161-
/** Whether the PR workflow runs and consumes the generated iOS-specific list. */
162156
readonly prWorkflowWiringFailures: readonly string[];
163-
/** Shared methods whose bodies differ between iOS and macOS builds. */
164157
readonly sharedPlatformBranchIds: readonly string[];
165-
/** Shared method bodies whose platform behavior could not be classified. */
166158
readonly sharedPlatformBranchFailures: readonly string[];
167159
};
168160

@@ -212,7 +204,6 @@ function laneReach(
212204
);
213205
}
214206

215-
/** Run iOS-only methods and shared methods with platform-dependent bodies. */
216207
export function iosPrTestIdentifiers(
217208
declaredTests: readonly DeclaredTest[],
218209
sharedPlatformBranchIds: readonly string[],

0 commit comments

Comments
 (0)