Skip to content

Harden Skia-sync conflict policy, allow durable gn args, and split skill vs workflow#4258

Merged
mattleibow merged 13 commits into
mainfrom
mattleibow-skia-sync-release-branch
Jun 29, 2026
Merged

Harden Skia-sync conflict policy, allow durable gn args, and split skill vs workflow#4258
mattleibow merged 13 commits into
mainfrom
mattleibow-skia-sync-release-branch

Conversation

@mattleibow

@mattleibow mattleibow commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Follow-up to the mode=main (tip) work (#4254) and release-line targeting (#4239). The first real tip run surfaced two rough edges in the upstream-sync automation and exposed that a chunk of general Skia-update knowledge lived only in the workflow prompt (so the update-skia skill couldn't drive it locally). Then, watching real runs, a third rough edge appeared: the conclusion job mislabeled successful syncs as "no-op".

Sections 1–3 are docs/prompt-only (no product code; prompt-body edits, so frontmatter_hash is unchanged for those). Section 4 is the one workflow-config change — it edits the workflow frontmatter (safe-outputs), so unlike the prompt-body edits it does regenerate auto-skia-sync.lock.yml.

1. Verify-upstream-or-reapply conflict resolution (do it right, don't pick a side)

A tip merge is ~291 commits ahead of our submodule base, so it conflicts on every file carrying an [M1xx] fork cherry-pick. The old guidance ("keep ours" / "resolve what you reasonably can") risks two failure modes:

  • --theirs → silently drops a not-yet-upstreamed fork patch.
  • --oursfreezes a stale form of a patch upstream has since refined (e.g. our SDF-LCD patch used getMaxScale(); upstream relanded it as sk_ieee_float_divide(1.f, getMinScale())).

Replaced with an explicit, auditable policy: for each conflicted file, classify every fork patch as upstreamed (take upstream's refined form, record the SHA) or not upstreamed (re-apply our patch on top of upstream) — never a blanket --theirs/--ours, never a silent drop. A mandatory before-merge snapshot of fork patches is cross-referenced so every fork patch on a conflicted file lands in the "Conflicts resolved" table as upstreamed or re-applied. A patch that is neither is a lost patch — stop and fix it.

Applied consistently in known-gotchas.md (gotcha #15, rewritten), SKILL.md (Phase 5 conflict step + audit), and auto-skia-sync.md (tip-mode note).

Why nothing was actually lost in #4254: the merge is a real two-parent git merge (a2658b7 has parents b16789e and upstream e793ca2), so all fork commits remain in history. Every [M150] patch had genuinely been upstreamed, each with a verified SHA — the "dropped" patches were only redundant diff content converging with upstream. This change makes that safety guaranteed rather than lucky.

2. Allow a required new gn arg through build.cake

The tip build needed skia_use_partition_alloc=false because upstream now defaults skia_use_partition_alloc=is_clang, while our DEPS deliberately disables third_party/externals/partition_alloc. Skia ships an official zero-overhead noop raw_ptr for exactly this case (MiraclePtr fallback "because partition_alloc dependency is missing"), so =false is the supported embedder path — not a hack. The agent had to pass it as a one-off --gnArgs CLI flag purely because the rule banned all build.cake edits, leaving durable config non-durable.

Relaxed the rule into two tiers:

  • Still forbidden: changing compiler/linker flags (or scripts/infra/native/**) to silence a host build error — those break the platforms the Linux-only sync never builds.
  • Now allowed: adding a genuinely required new upstream gn arg to the affected platforms' native/**/build.cake gn-args lists (the single source of truth, next to the existing skia_use_* toggles), flagged in both PR summaries for cross-platform human review.

Sequencing matters: skia_use_partition_alloc does not exist in m150, so baking it in now would break the current build with "unknown gn arg." The relaxed rule lets the next tip/milestone merge add the toggle in-context — shipping it alongside the milestone-bearing submodule, never before.

partition_alloc recommendation (for the eventual m151 bump): keep it disabled via the noop (=false) baked into build.cake, rather than vendoring the Chromium allocator. The noop is Google's own supported path; our threat model ≠ Chrome's (UAF mitigation has marginal value for a library in trusted .NET apps); vendoring adds a large Chromium dep + binary bloat + ongoing DEPS-roll maintenance across our full platform matrix. Even upstream has flip-flopped on the default. Revisit only if we ever want raw_ptr hardening and accept the cross-platform dependency.

3. Make the skill standalone; reduce the workflow to CI-specific overrides

The workflow prompt had accumulated general Skia-update knowledge that belongs in the update-skia skill, not in CI prose. Two concepts were documented only in the workflow, so the skill couldn't drive a local/manual run of them. Moved both into the skill (so it works standalone), and trimmed the workflow to minimal overrides + pointers — keeping the remaining duplicated reminders as short safety one-liners, since an unattended CI agent benefits from repeated guardrails.

Into the skill (now works locally):

  • main/tip mode is a first-class third option in Phase 1 (alongside main-target and release-line-target): the variable table gains a {UPSTREAM_REF} row + a tip column, plus a paragraph on the not-a-version-bump semantics and how Phase 2/5 milestone diffs become merge-base..upstream/main for the tip. Phase 5's merge command is generalized to upstream/{UPSTREAM_REF}.
  • Required-new-gn-arg rule in Phase 7 (error-table row + note), backed by a new gotcha Text measurement support #23 with the full partition_alloc worked example and the milestone-sequencing caveat.

Out of the workflow (body-only edits → lock byte-identical): the mode/tip note and the FORBIDDEN/ALLOWED build.cake block collapse to short pointers into the skill, keeping only the genuinely CI-specific parts — can't apt-install in the sandbox, a missing host dependency is a workflow bug (fix the install step, don't hack shared flags), and the Linux-only-build cross-platform-review reminder.

4. Stop mislabeling a real sync as a "no-op" (honest completion signal)

Watching the first live runs, a sync that actually merged upstream, built, tested, and opened both PRs was reported by the gh-aw conclusion job as a no-op — which then tried (and failed, the workflow has no issues: write) to file a "no-op runs" issue. Misleading on two counts: a PR-producing run is not a no-op, and the failed issue step added red noise.

The cause is the two-subsystem split this workflow uses on purpose. safe-outputs: staged: true blocks the agent from creating anything directly; the real GitHub writes (push both repos, open both PRs) are done by the host post-step skia-sync-push-prs.sh with SKIASHARP_AUTOBUMP_TOKEN — gh-aw can't open the mono/skia PR itself because the submodule's merge commits live in a nested repo it only sees as a gitlink. With noop as the agent's only available completion signal, every run — including real syncs — signalled noop, and the conclusion classified on that alone.

Give the agent an honest signal instead:

  • Declare create-pull-request in safe-outputs, kept staged (preview-only: no real PR, no branch push, no patch — the safe_outputs job runs on ubuntu-slim with permissions: {} and never touches the workspace). The agent calls it as its completion signal when it did work, so the run registers as a pull-request output rather than a no-op. Real PRs are still opened only by the post-step.
  • Set noop: report-as-issue: false (the gh-aw default is true). noop is now reserved for genuine no-work runs and no longer tries to file an issue the workflow can't create.
  • create_issue is no longer offered to the agent (it was never used — the prompt already forbade it).
  • The prompt body gains a short "Completion signal" section: call create_pull_request when skia-sync-env.sh was written, noop only when it wasn't.

Unlike sections 1–3, this edits the workflow frontmatter, so auto-skia-sync.lock.yml is regenerated via gh aw compile (safe-outputs config + the #4260 name; never hand-edited).

Rebased on main

Picked up #4260 (regroup/rename GitHub Actions workflows), which renamed this workflow Skia Upstream SyncSync - Skia Upstream. The merge was clean and gh aw compile reproduced the lock with a 0-diff, so the rename and the Section-4 safe-outputs change coexist correctly. Also confirmed #4267's new support-status model (versions.json: stable 4.148, preview 4.150; the SkiaSharp minor number is the Skia milestone) is consistent with the skill's release/<major>.<milestone>.x mapping — no change needed.

Validation

  • gh aw compile auto-skia-sync0 errors (4 pre-existing warnings).
  • Sections 1–3 are prompt-body edits → no lock impact. Section 4 edits the frontmatter, so auto-skia-sync.lock.yml is regenerated and committed (this supersedes the earlier "no lock change / 3 files" note).
  • End-to-end run #28269474099 (mode=main, real 2-commit merge): the agent emitted create_pull_request (staged, title [skia-sync] Update Skia to upstream main HEAD (e47bb0549c)); the safe_outputs job logged 0 noop message(s) and wrote a staged PR preview; the conclusion logged No noop items found with no failed issue step; and the host post-step still pushed skia-sync/main to both repos and updated the real PRs ([skia-sync] Merge upstream Skia main (tip) #4263 + Making the Forms views more extendable #269). All jobs green.
  • Net PR diff = 4 files: SKILL.md, references/known-gotchas.md, auto-skia-sync.md, auto-skia-sync.lock.yml.

mattleibow and others added 9 commits June 23, 2026 19:39
Let the Skia sync workflow and update-skia skill target a
release/<major>.<milestone>.x line (in both mono/SkiaSharp and mono/skia)
instead of only main, derived automatically from the resolved milestone.

- auto-skia-sync.md: pre-activation detects the release line from the
  target milestone, exposes is_release/base_branch/skia_base_branch/
  head_branch, fails fast if the mono/skia release branch is missing, and
  adapts the skip-check; host submodule-align step and prompt body use the
  resolved base/head branches.
- skia-sync-push-prs.sh: consume HEAD_BRANCH/BASE_BRANCH/SKIA_BASE_BRANCH/
  IS_RELEASE and target the right base branches with release-aware titles.
- update-skia skill: document release-target mode (Phase 1 base detection,
  parametric Phase 4 + Phase 11, fail-if-missing mono/skia branch).

Creation of the matching mono/skia release branch is owned by the release
process and will be handled in a separate change to the release-branch skill.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the milestone/branch-line resolution out of the inline workflow YAML and
into two committed, testable scripts:

- skia-sync-detect.sh: the single source of truth for mode/target/base-branch
  resolution. Emits key=value to $SKIA_SYNC_OUT (default $GITHUB_OUTPUT); --gate
  adds the upstream-exists / already-merged checks. Run by both the pre_activation
  step (--gate, writes job outputs) and the agent align step (sourced, since that
  job can't read pre_activation outputs).
- skia-sync-align-submodule.sh: the submodule alignment, driven by the sourced
  base_branch / skia_base_branch.

The pre_activation job now sparse-checks-out .github/scripts so it can call the
script. This collapses the two large inline bash blocks to ~1 and ~5 lines and
removes the duplicated branch-resolution logic.

Behaviour is preserved for the main line and the single-match release path. The
extraction also folds in two release-resolution fixes from review that were not
yet in the previous commit: the strictly-older check is now a numeric compare
(`-lt` instead of `!=`), and a milestone matching multiple release branches now
hard-fails instead of silently picking the first via `head -1`.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add an engine: block pinning model claude-opus-4.6 (overriding the default
claude-sonnet-4.6). Upstream merge/conflict resolution and native build-fix
reasoning are hard, so the stronger model is worth the higher AI-credit cost
for this workflow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Opus 4.7 carries the same 5x AI-credit multiplier as 4.6, so move to the
newer model for the upstream merge/conflict-resolution reasoning.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
native/linux/build.cake builds libSkiaSharp/libHarfBuzzSharp with
-stdlib=libc++. On the real CI that runtime comes from the .NET
cross-compilation image, but this workflow builds on a bare Ubuntu host
where the agent cannot apt-install anything (no apt/sudo in the AWF
chroot, and the firewall blocks the OS package mirrors).

Install libc++-dev + libc++abi-dev in the host pre-agent step so the
unmodified native build compiles, and tell the agent not to patch native
build files or compiler flags to work around a missing dependency.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The cron→mode mapping (7 AM → current, 5 PM → latest, else → next) was the
only workflow-coupled knowledge inside skia-sync-detect.sh — it hardcoded the
literal cron strings and read mode/milestone/schedule from INPUT_MODE,
INPUT_MILESTONE and SCHEDULE env vars.

Move that mapping into the workflow, next to where the crons are declared, as a
single GitHub Actions expression. The detector now takes real --mode/--milestone
arguments and no longer knows anything about cron, so it is self-contained and
unit-testable (pass --mode latest instead of faking SCHEDULE='0 17 * * *').

mode is staged into an env var (not interpolated straight into run:) so the
free-form milestone dispatch input cannot inject shell — the same anti-injection
safety the previous env-based wiring had. Behavior is unchanged: validated that
--mode current/next/latest, the default, an explicit --milestone override, an
empty --milestone, and an unknown arg all resolve exactly as before.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Final review pass over the skia-sync scripts:

- Harden skia-sync-detect.sh arg parsing: a value-less --mode/--milestone now
  reports a clear error and exits 2 instead of tripping set -e on a double
  shift. Matters now that the detector is meant to be run by hand for testing.
- Flatten the multi-match release-branch list with paste instead of the
  $(echo $VAR) word-splitting idiom (SC2116/SC2086).
- Mark the runtime-generated skia-sync-env.sh source with a shellcheck
  source=/dev/null directive (SC1091).

All three scripts are now shellcheck-clean at style level; behavior verified
unchanged for every valid invocation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…release-branch

# Conflicts:
#	.github/scripts/skia-sync-detect.sh
#	.github/scripts/skia-sync-push-prs.sh
#	.github/workflows/auto-skia-sync.lock.yml
#	.github/workflows/auto-skia-sync.md
The first `mode=main` (tip) run (PR #4254 validation) surfaced two rough
edges in the upstream-sync automation worth fixing before tip-mode becomes
routine.

~~ Verify-upstream-or-reapply conflict resolution ~~

A tip merge is ~291 commits ahead of our submodule base, so it conflicts on
every file that carries a `[M1xx]` fork cherry-pick. The old guidance was a
blunt "keep ours" / "resolve what you reasonably can", which risks two
failure modes: silently dropping a not-yet-upstreamed fork patch with
`--theirs`, or freezing a stale form of a patch upstream has since refined
with `--ours` (e.g. our SDF-LCD patch used `getMaxScale()`; upstream relanded
it as `sk_ieee_float_divide(1.f, getMinScale())`).

Replace it with an explicit, auditable policy: for each conflicted file,
classify every fork patch as *upstreamed* (take upstream's refined form) or
*not upstreamed* (re-apply our patch on top of upstream) — never a blanket
`--theirs`/`--ours`, never a silent drop. A mandatory before-merge snapshot
of fork patches must be cross-referenced so every fork patch on a conflicted
file lands in the PR's "Conflicts resolved" table as upstreamed or re-applied.
A patch that is neither is a lost patch — stop and fix it. Applied in
gotcha #15, SKILL.md Phase 5, and the workflow's tip-mode note.

~~ Allow a required new gn arg through build.cake ~~

The tip build needed `skia_use_partition_alloc=false` because upstream now
defaults `skia_use_partition_alloc=is_clang` while our DEPS deliberately
disables `third_party/externals/partition_alloc` (Skia ships an official
zero-overhead noop `raw_ptr` for exactly this case). The agent passed it as a
one-off `--gnArgs` CLI flag because the rule banned all `build.cake` edits —
durable config ending up non-durable.

Relax the rule into two tiers: host/flag hacks to silence a build error stay
FORBIDDEN (they break the platforms the Linux-only sync never builds), but a
genuinely *required* new upstream gn arg may be added to the affected
platforms' `native/**/build.cake` gn-args lists (the single source of truth,
next to the existing `skia_use_*` toggles) and flagged in both PR summaries for
cross-platform human review. This lets the next tip merge bake the toggle in
durably — and correctly ships it alongside the milestone-bearing submodule, so
it never breaks the current m150 build (which has no such gn arg yet).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

📦 Try the packages from this PR

Warning

Do not run these scripts without first reviewing the code in this PR.

Step 1 — Download the packages

bash / macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.sh | bash -s -- 4258

PowerShell / Windows:

iex "& { $(irm https://raw.githubusercontent.com/mono/SkiaSharp/main/scripts/get-skiasharp-pr.ps1) } 4258"

Step 2 — Add the local NuGet source

dotnet nuget add source ~/.skiasharp/hives/pr-4258/packages --name skiasharp-pr-4258
More options
Option Description
--successful-only / -SuccessfulOnly Only use successful builds
--force / -Force Overwrite previously downloaded packages
--list / -List List available artifacts without downloading
--build-id ID / -BuildId ID Download from a specific build

Or download manually from Azure Pipelines — look for the nuget artifact on the build for this PR.

Remove the source when you're done:

dotnet nuget remove source skiasharp-pr-4258

@github-actions

Copy link
Copy Markdown
Contributor

📖 Documentation Preview

The documentation for this PR has been deployed and is available at:

🔗 View Staging Site
🔗 View Staging Docs
🔗 View Staging Gallery (Blazor)
🔗 View Staging Gallery (Uno Platform)
🔗 View Staging SkiaFiddle

This preview will be updated automatically when you push new commits to this PR.


This comment is automatically updated by the documentation staging workflow.

… workflow

The auto-skia-sync workflow prompt had accumulated general Skia-update
knowledge that belongs in the update-skia skill, not in CI-specific prose.
Two concepts in particular were documented ONLY in the workflow, so the
skill couldn't drive a local/manual run of them:

  1. `main`/tip mode — syncing from the very tip of google/skia `main`
     (HEAD) instead of a `chrome/m{N}` milestone branch. Bleeding-edge,
     `CURRENT == TARGET`, NOT a version bump, but may carry new APIs.
  2. The "a required new upstream gn arg goes in native/**/build.cake,
     not a one-off --gnArgs flag" rule (e.g. skia_use_partition_alloc
     =false when our DEPS doesn't vendor partition_alloc).

Move both into the skill so it works standalone, and reduce the workflow
to minimal CI-specific overrides + pointers (option B: duplicated
reminders kept as short safety one-liners, since the unattended CI agent
benefits from repeated guardrails).

Skill (works locally now):
  * SKILL.md Phase 1: tip mode is a first-class third option alongside
    main-target and release-line-target — variable table gains a
    {UPSTREAM_REF} row and a tip column, plus a paragraph covering the
    not-a-version-bump semantics and how Phase 2/5 milestone diffs become
    merge-base..upstream/main for the tip.
  * SKILL.md Phase 5: merge command generalized to upstream/{UPSTREAM_REF}.
  * SKILL.md Phase 7: new error-table row + note for a required new gn
    arg, cross-referencing the gotcha.
  * known-gotchas.md: new gotcha #23 — partition_alloc worked example
    (why our DEPS un-vendors it, why the noop raw_ptr / =false is the
    supported embedder path, not vendoring) and the milestone-sequencing
    caveat (the arg doesn't exist before its upstream branch point, so
    only add it alongside the submodule that carries it).

Workflow (body-only edits; lock stays byte-identical, frontmatter
unchanged):
  * Mode/tip note and the FORBIDDEN/ALLOWED build.cake block collapsed
    to short pointers into the skill, keeping the genuinely CI-specific
    parts: can't apt-install in the sandbox, a missing host dependency is
    a workflow bug (fix the install step, don't hack shared flags), and
    the Linux-only-build cross-platform review reminder.

gh aw compile auto-skia-sync: 0 errors, 4 pre-existing warnings, lock
unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mattleibow mattleibow changed the title Harden Skia-sync conflict policy and allow durable gn args in build.cake Harden Skia-sync conflict policy, allow durable gn args, and split skill vs workflow Jun 26, 2026
mattleibow and others added 3 commits June 26, 2026 22:10
Follow-up on the skill/workflow split (commit 35ee068): an Opus 4.7
read-only review of SKILL.md + auto-skia-sync.md flagged two live bugs and
several consistency gaps left over from the release-line/tip-mode refactor.
The workflow points the agent straight at named phases/steps in the skill, so
a hardcoded `origin/main` there silently does the wrong thing on a release-line
or tip sync. Fixes:

Blocking (live refactor misses — `origin/main` should follow the resolved base):
  * Phase 9 step 1: diff unwrapped bindings against `origin/{BASE_BRANCH}`,
    not `origin/main`.
  * Phase 5 "before proceeding" gate: describe the parent/submodule base as
    `origin/{BASE_BRANCH}` instead of `origin/main`.

Should-fix (sync/consistency):
  * Phase 5 step 5 source-file verification: parameterize the milestone-pair
    diff to `$(git merge-base {SKIA_BASE_BRANCH} upstream/{UPSTREAM_REF})..
    upstream/{UPSTREAM_REF}` so it works for tip mode too.
  * Phase 10 test suite: stop leaking the workflow-only `/tmp/gh-aw/agent`
    path into the standalone skill — use `/tmp/skia-test-output.txt` and note
    that the automated workflow overrides it to the artifact path. Mirror the
    override note in the workflow's Phase 10 file-writing section.
  * Phase 1 step 5: restructure the three modes (main target / release-line
    target / `main` tip) into clearly-labeled blocks; the closing "use these
    values" line now lists `{UPSTREAM_REF}` and `chrome/m{TARGET}` so the
    merge-from ref is covered. Name Phase 2 step 4 as the only milestone-pair
    diff needing tip substitution (Phase 5 already uses `{UPSTREAM_REF}`).
  * Phase 4 preamble and Phase 11 branch-target note: add `main`/tip mode to
    the per-mode branch examples.

Body-only edits: `gh aw compile auto-skia-sync` = 0 errors and the
`.lock.yml` is byte-identical (the lock embeds only frontmatter). Gotchas are
intentionally not renumbered per the reviewer.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A successful upstream-sync run was being mislabeled a "no-op" in the gh-aw
conclusion job, and the job then tried (and failed) to file a "no-op runs"
issue. Both were misleading: the run had actually merged upstream Skia, built,
tested, and produced two real PRs.

The cause is the two-subsystem split this workflow uses. Real GitHub writes
(push both repos, open both PRs) happen in the custom post-step
`skia-sync-push-prs.sh` with SKIASHARP_AUTOBUMP_TOKEN — gh-aw itself can't open
the mono/skia PR because the submodule's merge commits live in a nested repo it
only sees as a gitlink, and `safe-outputs: staged: true` deliberately blocks the
agent from creating anything directly. With only `noop` available as a
completion signal, every run — including real syncs — signalled `noop`, and the
conclusion job classified on that alone.

Give the agent an honest signal instead:

  * Declare `create-pull-request` in safe-outputs, kept STAGED (preview-only:
    no real PR, no branch push, no patch — the safe_outputs job runs on
    ubuntu-slim with `permissions: {}` and never touches the workspace). The
    agent calls it as its completion signal when it did work, so the run
    registers as a pull-request output rather than a no-op. Real PRs are still
    opened only by the post-step.
  * Set `noop: report-as-issue: false` (the gh-aw default is true). `noop` is
    now reserved for genuine no-work runs and no longer tries to file an issue
    the workflow has no `issues: write` permission to create.
  * Update the prompt's "Completion signal" guidance: call `create_pull_request`
    when `skia-sync-env.sh` was written, `noop` only when it was not.

`create_issue` is no longer offered to the agent (it was never used — the prompt
already forbade it). `gh aw compile` = 0 errors; the 4 pre-existing warnings
(3 fixed-schedule + storage.googleapis.com) are unchanged.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mattleibow
mattleibow merged commit b62adf1 into main Jun 29, 2026
5 of 6 checks passed
@mattleibow
mattleibow deleted the mattleibow-skia-sync-release-branch branch June 29, 2026 15:40
@mattleibow mattleibow added this to the 4.150.0-rc.1 milestone Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant