Skip to content

Commit 3d5bf79

Browse files
committed
Merge origin/main and address review feedback
Resolve the overlapping bundler-debug defaults, correct the universal-build macro spelling, and safely fall back when generated weak TPA symbols are incomplete. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b6c903d4-d655-47d4-9e0c-636bea8e7d37
2 parents 1f367cc + c2f4a1d commit 3d5bf79

312 files changed

Lines changed: 6434 additions & 3546 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.agents/skills/macios-xcode-beta-update/SKILL.md‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Run this workflow from the macios repository root.
1212
Collect or confirm:
1313
- Target Xcode version (for example `26.4`)
1414
- Beta number (for example `2`)
15+
- Azure Artifacts package version (for example `26.4.0-beta.2`)
16+
- Xcode product build version (for example `17E5212f`)
1517
- Xcode URL (for example `https://dl.internalx.com/internal-files/xcodes/Xcode_26.4_beta_2.xip`)
1618
- Optional prior bump PR to mirror
1719
- Whether to do this in two phases (non-test changes first, tests second)
@@ -26,9 +28,38 @@ Apply minimal, surgical changes in these files:
2628
- `NUGET_HARDCODED_PRERELEASE_IDENTIFIER=xcode<major.minor>`
2729
- `NUGET_HARDCODED_PRERELEASE_BRANCH=xcode<major.minor>`
2830
- `XCODE_VERSION=<major.minor>`
31+
- `XCODE_PACKAGE_NAME=xcode-apple-silicon`
32+
- `XCODE_PACKAGE_VERSION=<major.minor.patch-beta.number>`
33+
- `XCODE_BUILD_VERSION=<ProductBuildVersion>`
2934
- `XCODE_URL=<user-provided-xip-url>`
3035
- `XCODE_DEVELOPER_ROOT=/Applications/Xcode_<major.minor>.0-beta<beta>.app/Contents/Developer` (for betas)
3136

37+
`XCODE_DEVELOPER_ROOT` must name the same application that `XCODE_PACKAGE_VERSION`
38+
implies; `install-xcode.sh` refuses to run when the two disagree. The package version is
39+
strict SemVer (Azure Artifacts requires it) while the application name follows this
40+
repository's convention, so they are deliberately spelled differently:
41+
42+
| Release | `XCODE_PACKAGE_VERSION` | `XCODE_DEVELOPER_ROOT` application |
43+
| --- | --- | --- |
44+
| beta 1 | `27.0.0-beta` | `Xcode_27.0.0-beta.app` |
45+
| beta 3 | `27.0.0-beta.3` | `Xcode_27.0.0-beta3.app` |
46+
| RC 1 | `27.0.0-rc` | `Xcode_27.0.0-rc.app` |
47+
| RC 2 | `27.0.0-rc.2` | `Xcode_27.0.0-rc.2.app` |
48+
| stable | `27.0.0` | `Xcode_27.0.0.app` |
49+
| patch | `27.0.1` | `Xcode_27.0.1.app` (`XCODE_VERSION` stays `27.0`) |
50+
51+
Betas drop the dot before the ordinal, release candidates keep it, and the first beta or
52+
RC carries no ordinal at all. `Xcode_26.3.0-rc2.app` is wrong: it has been written twice
53+
and corrected both times. Note that `XCODE_BUILD_VERSION` is what actually distinguishes
54+
one beta or RC from the next, so a stale value passes every path check and only fails
55+
once the package is installed.
56+
57+
Before queuing CI, verify that the matching immutable package exists — with its
58+
Apple-signed XIP and `xcode-metadata.json` — in **both** feeds, because the two
59+
pipelines resolve the same coordinates in their own organization:
60+
- `devdiv/DevDiv/macios-tools-internal`
61+
- `dnceng/internal/macios-tools-internal`
62+
3263
2. `Make.versions`
3364
- Bump:
3465
- `IOS_NUGET_OS_VERSION`

‎.github/skills/gh-stack/SKILL.md‎

Lines changed: 872 additions & 0 deletions
Large diffs are not rendered by default.

‎.github/skills/update-expected-app-size/SKILL.md‎

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ Download updated expected app size files from Azure DevOps artifacts for the cur
2121

2222
The app size tests (`tests/dotnet/UnitTests/AppSizeTest.cs`) compare the built app's size and preserved APIs against expected files stored in `tests/dotnet/UnitTests/expected/`. When the test detects a difference and `WRITE_KNOWN_FAILURES` is not set, it writes the updated expected file to `$(Build.ArtifactStagingDirectory)/updated-expected-sizes/`, and a pipeline step publishes this directory as a build artifact.
2323

24-
The artifact name follows the pattern `{uploadPrefix}updated-expected-sizes-{testPrefix}-{attempt}` (e.g., `updated-expected-sizes-dotnettests_ios-1`). Inside the artifact, files are named after the test variant:
25-
- `{Platform}-{Variant}-size.txt` — e.g., `iOS-MonoVM-size.txt`, `iOS-MonoVM-interpreter-size.txt`, `iOS-NativeAOT-TrimmableStatic-size.txt`, `MacOSX-CoreCLR-Interpreter-size.txt`
26-
- `{Platform}-{Variant}-preservedapis.txt` — e.g., `iOS-MonoVM-preservedapis.txt`, `MacCatalyst-MonoVM-interpreter-preservedapis.txt`
24+
The artifact name follows the pattern `{uploadPrefix}updated-expected-sizes-{testPrefix}-{attempt}` (e.g., `updated-expected-sizes-dotnettests_ios-1`). Because the expected files can be very big, the test uploads a unified **diff** for each changed expected file rather than the whole file. Inside the artifact, files are named after the test variant with a `.diff` suffix:
25+
- `{Platform}-{Variant}-size.txt.diff` — e.g., `iOS-MonoVM-size.txt.diff`, `iOS-MonoVM-interpreter-size.txt.diff`, `iOS-NativeAOT-TrimmableStatic-size.txt.diff`, `MacOSX-CoreCLR-Interpreter-size.txt.diff`
26+
- `{Platform}-{Variant}-preservedapis.txt.diff` — e.g., `iOS-MonoVM-preservedapis.txt.diff`, `MacCatalyst-MonoVM-interpreter-preservedapis.txt.diff`
2727

28-
The expected files on disk are at:
28+
Each diff is a unified diff (relative to the repository root) that can be applied with `git apply -p1` or `patch -p1`. The expected files on disk are at:
2929
- `tests/dotnet/UnitTests/expected/{Platform}-{Variant}-size.txt`
3030
- `tests/dotnet/UnitTests/expected/{Platform}-{Variant}-preservedapis.txt`
3131

@@ -85,15 +85,17 @@ If `az` is not available or not authenticated, direct the user to download manua
8585

8686
### 4. Place the files
8787

88-
Extract the downloaded artifact zip and place the files in the expected directory:
88+
Extract the downloaded artifact zip and apply each diff to the expected directory from the repository root:
8989

9090
```bash
91-
EXPECTED_DIR="tests/dotnet/UnitTests/expected"
9291
unzip -o artifact.zip -d /tmp/updated-sizes/
93-
cp /tmp/updated-sizes/*/*.txt "$EXPECTED_DIR/"
92+
# Each '*.txt.diff' is a unified diff relative to the repository root.
93+
for diff in /tmp/updated-sizes/*/*.txt.diff; do
94+
git apply -p1 "$diff"
95+
done
9496
```
9597

96-
The files inside the zip already have the correct names (e.g., `iOS-MonoVM-size.txt`) and can be copied directly.
98+
The diffs reference `tests/dotnet/UnitTests/expected/<name>.txt` directly, so applying them updates (or creates) the expected files in place. If a diff fails to apply cleanly (e.g., the expected file changed since the CI build), re-run the failing app size test locally with `WRITE_KNOWN_FAILURES=1` to regenerate the file (see the "Run Locally" fallback).
9799

98100
### 5. Verify and commit
99101

@@ -112,7 +114,7 @@ If automated download fails (auth issues, etc.), provide the user with:
112114
1. The Azure DevOps build URL
113115
2. Instructions to navigate to the build → Summary → Artifacts section
114116
3. Look for individual artifacts whose names contain `updated-expected-sizes`
115-
4. Download the artifact zip, extract it, and copy the `.txt` files (e.g., `iOS-MonoVM-interpreter-size.txt`) into `tests/dotnet/UnitTests/expected/`
117+
4. Download the artifact zip, extract it, and apply the `.txt.diff` files (e.g., `iOS-MonoVM-interpreter-size.txt.diff`) from the repository root with `git apply -p1 <file>`
116118

117119
## Fallback: Run Locally
118120

‎.github/workflows/agentics-maintenance.yml‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ jobs:
158158
operation: ${{ steps.record.outputs.operation }}
159159
steps:
160160
- name: Checkout repository
161-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
161+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
162162
with:
163163
persist-credentials: false
164164

@@ -249,7 +249,7 @@ jobs:
249249
run_url: ${{ steps.record.outputs.run_url }}
250250
steps:
251251
- name: Checkout actions folder
252-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
252+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
253253
with:
254254
sparse-checkout: |
255255
actions
@@ -297,7 +297,7 @@ jobs:
297297
issues: write
298298
steps:
299299
- name: Checkout repository
300-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
300+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
301301
with:
302302
persist-credentials: false
303303

@@ -343,7 +343,7 @@ jobs:
343343
issues: write
344344
steps:
345345
- name: Checkout repository
346-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
346+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
347347
with:
348348
persist-credentials: false
349349

@@ -448,7 +448,7 @@ jobs:
448448
issues: write
449449
steps:
450450
- name: Checkout repository
451-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
451+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
452452
with:
453453
persist-credentials: false
454454

@@ -577,7 +577,7 @@ jobs:
577577
issues: write
578578
steps:
579579
- name: Checkout repository
580-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
580+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
581581
with:
582582
persist-credentials: false
583583

‎.github/workflows/apply-gist.yml‎

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -130,50 +130,93 @@ jobs:
130130
core.setOutput('repo_full_name', pr.head.repo.full_name);
131131
132132
- name: Checkout PR branch
133-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
133+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
134134
with:
135135
ref: ${{ steps.pr-branch.outputs.ref }}
136136
repository: ${{ steps.pr-branch.outputs.repo_full_name }}
137137
token: ${{ secrets.GITHUB_TOKEN }}
138138
persist-credentials: true
139139

140-
- name: Download and apply gist files
140+
- name: Download and apply gist diffs
141141
env:
142142
GIST_ID: ${{ steps.parse.outputs.gist_id }}
143143
run: |
144144
EXPECTED_DIR="tests/dotnet/UnitTests/expected"
145145
mkdir -p "$EXPECTED_DIR"
146-
export EXPECTED_DIR
147146
148-
# Download gist metadata to get file URLs. The Gists API isn't accessible to the
149-
# GitHub Actions token (a GitHub App installation token), so fetch it unauthenticated.
147+
DIFF_DIR="$(mktemp -d)"
148+
export DIFF_DIR EXPECTED_DIR
149+
150+
# Download gist metadata to get file URLs. The Gists API isn't accessible to the GitHub Actions token
151+
# (a GitHub App installation token), so fetch it unauthenticated.
150152
if ! GIST_JSON=$(curl -fSL -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" -H "User-Agent: dotnet-macios-apply-gist" "https://api.github.com/gists/$GIST_ID"); then
151153
echo "Failed to fetch gist '$GIST_ID' (404/403/rate limit?)." >&2
152154
exit 1
153155
fi
156+
157+
# Newer builds upload a unified diff ('<name>.txt.diff') for each changed expected file, instead of the
158+
# entire (potentially very large) expected file. For backwards compatibility we still accept gists that
159+
# contain the full expected files ('<name>.txt'). Download and validate everything, applying diffs and
160+
# writing full files below.
154161
echo "$GIST_JSON" | python3 -c "
155162
import json, sys, urllib.request, os, re
156163
157164
gist = json.load(sys.stdin)
165+
diff_dir = os.environ['DIFF_DIR']
158166
expected_dir = os.environ['EXPECTED_DIR']
159167
files = gist['files']
160-
# Only allow known expected-file patterns
161-
allowed_pattern = re.compile(r'^[A-Za-z0-9]+-[A-Za-z0-9-]+-(size|preservedapis)\.txt$')
168+
# Allowed expected-file name, and the same name with a '.diff' suffix (a unified diff of that file).
169+
allowed_diff = re.compile(r'^[A-Za-z0-9]+-[A-Za-z0-9-]+-(size|preservedapis)\.txt\.diff$')
170+
allowed_full = re.compile(r'^[A-Za-z0-9]+-[A-Za-z0-9-]+-(size|preservedapis)\.txt$')
171+
applied = 0
162172
for filename, file_info in files.items():
163-
if not allowed_pattern.match(filename):
173+
is_diff = bool(allowed_diff.match(filename))
174+
is_full = bool(allowed_full.match(filename))
175+
if not is_diff and not is_full:
164176
print(f'Skipping file with unexpected name: {filename}')
165177
continue
166178
content = file_info.get('content')
167179
if content is None:
168180
# Large files need to be fetched from raw_url
169181
raw_url = file_info['raw_url']
170182
content = urllib.request.urlopen(raw_url).read().decode('utf-8')
171-
dest = os.path.join(expected_dir, filename)
172-
with open(dest, 'w') as f:
173-
f.write(content)
174-
print(f'Applied: {filename}')
183+
# Gist content can be served with CRLF line endings; normalize to LF
184+
# so 'git apply' doesn't fail against the repo's LF expected files.
185+
content = content.replace('\r\n', '\n').replace('\r', '\n')
186+
if is_diff:
187+
# The diff for '<name>.txt.diff' is only allowed to touch 'tests/dotnet/UnitTests/expected/<name>.txt'.
188+
expected_target = 'tests/dotnet/UnitTests/expected/' + filename[:-len('.diff')]
189+
allowed_targets = ('/dev/null', 'a/' + expected_target, 'b/' + expected_target)
190+
for line in content.splitlines():
191+
if line.startswith('--- ') or line.startswith('+++ '):
192+
# Strip a trailing tab + timestamp if present, then verify the target path.
193+
target = line[4:].split('\t', 1)[0].strip()
194+
if target not in allowed_targets:
195+
print(f'Rejecting diff {filename}: unexpected target path: {target}')
196+
sys.exit(1)
197+
dest = os.path.join(diff_dir, filename)
198+
with open(dest, 'w') as f:
199+
f.write(content)
200+
print(f'Downloaded diff: {filename}')
201+
else:
202+
# Full expected file: write it directly into the expected directory.
203+
dest = os.path.join(expected_dir, filename)
204+
with open(dest, 'w') as f:
205+
f.write(content)
206+
print(f'Applied full file: {filename}')
207+
applied += 1
208+
if applied == 0:
209+
print('No applicable files found in gist.')
210+
sys.exit(1)
175211
"
176212
213+
# Apply each diff. 'git apply' handles both modifications of existing files and creation of new files.
214+
shopt -s nullglob
215+
for diff in "$DIFF_DIR"/*.diff; do
216+
echo "Applying $(basename "$diff")..."
217+
git apply -p1 --verbose "$diff"
218+
done
219+
177220
- name: Commit and push
178221
env:
179222
GIST_URL: ${{ steps.parse.outputs.gist_url }}

‎.github/workflows/autoformat-v2.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414

1515
steps:
1616
- name: 'Checkout'
17-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
17+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
1818
with:
1919
ref: ${{ github.head_ref }}
2020
fetch-depth: 1
@@ -59,7 +59,7 @@ jobs:
5959

6060
steps:
6161
- name: 'Checkout'
62-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
62+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
6363
with:
6464
repository: ${{ github.event.pull_request.head.repo.full_name }}
6565
ref: ${{ github.event.pull_request.head.sha }}

‎.github/workflows/bump-global-json.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
contains(github.event.pull_request.title, 'Update dependencies from dotnet/')
2222
steps:
2323
- name: 'Checkout repo'
24-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
24+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
2525
with:
2626
fetch-depth: 0
2727
repository: ${{ github.event.pull_request.head.repo.full_name }}

‎.github/workflows/ci-postmortem.lock.yml‎

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.github/workflows/code-radiator.lock.yml‎

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.github/workflows/copilot-setup-steps.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919

2020
steps:
2121
- name: Checkout repository
22-
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
22+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
2323
with:
2424
persist-credentials: false
2525
- name: Install gh-aw extension

0 commit comments

Comments
 (0)