Skip to content

CI: Track c2pa-rs stable and RC release lines - #131

Merged
redaranj merged 4 commits into
mainfrom
ci/c2pa-rs-tracking-branches
Sep 8, 2026
Merged

redaranj merged 4 commits into
mainfrom
ci/c2pa-rs-tracking-branches

Conversation

@redaranj

Copy link
Copy Markdown
Member

Changes in this pull request

Adds track/c2pa-rs-stable and track/c2pa-rs-rc branches that continuously verify main builds and tests against upstream c2pa-rs's latest release and in-flight release candidates. The workflow opens a PR when stable passes the full matrix and an issue when anything breaks.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • All applicable changes have been documented
  • Any TO DO items (or similar) have been entered as GitHub issues and the link to that issue has been included in a comment

Adds track/c2pa-rs-stable and track/c2pa-rs-rc, two robot-owned branches
that are each main plus a single c2paVersion pin bump, hard-reset on every
sync. The stable tracker opens a promotion PR once a pin has passed both
the per-sync gate and the full emulator matrix; either tracker files a
deduplicated issue when it goes red and closes it on the next green sync.

Supersedes update-c2pa-core-sdk.yml, which had no prerelease filter, took
head -1 of a date-ordered release list, resolved off the c2pa-c-ffi-v* tag
family while build.gradle.kts downloads from c2pa-v*, and opened its bump
PR without having built anything.

Ported from contentauth/c2pa-swift#164, keeping the job graph, the script
exit-code contract and the issue wording identical so the two repos stay
diffable. The divergences are platform-forced: an ubuntu-latest sync job
driving an emulator rather than macOS driving a simulator, four Android
ABIs rather than seven Apple targets, and a two-step gate (make library,
then make tests-with-server) that separates an FFI signature break from a
behavioural one.

test.yml gains workflow_call so the tracker can invoke the full matrix
directly -- pushes made with GITHUB_TOKEN do not trigger other workflows --
and ignores pushes to track/** so tracker force-pushes do not fire it.
Codecov is skipped on tracker runs, which leaves the tracker needing no
secrets at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@redaranj
redaranj requested a review from scouten-adobe August 28, 2026 07:46
@redaranj redaranj changed the title CI: Track c2pa-rs stable and R release lines CI: Track c2pa-rs stable and RC release lines Aug 28, 2026
@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.21%. Comparing base (077035c) to head (3f9fa81).

Additional details and impacted files
@@            Coverage Diff            @@
##               main     #131   +/-   ##
=========================================
  Coverage     72.21%   72.21%           
  Complexity       38       38           
=========================================
  Files            62       62           
  Lines          2350     2350           
  Branches        286      286           
=========================================
  Hits           1697     1697           
  Misses          495      495           
  Partials        158      158           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Adds a third robot-owned tracking branch, track/c2pa-rs-main, alongside
the stable and rc trackers. Upstream publishes no prebuilt archives for
main, so the tracker clones c2pa-rs at the tip SHA, builds the four
Android targets of the c2pa-c-ffi crate with upstream's own
`make release TARGET=<triple>` packaging, and builds the AAR and runs the
instrumented suite against the result.

The Gradle download task gains an optional c2paArchiveDir property,
passed through by the Makefile as C2PA_ARCHIVE_DIR and resolved to an
absolute path. When set, downloadNativeLibraries takes
c2pa-*-<triple>.zip from that directory instead of downloading the
pinned release, and requires exactly one match per target; the version is
globbed because self-built archives carry upstream's working version.
Release mode is unchanged. The version stamp is written as a literal in
local mode, since c2paVersion is not a usable cache key when the pin
holds still and the archive contents move -- which also makes the first
release-mode run after a local one invalidate. The same property lets a
developer build against a local c2pa-rs checkout, and the README
documents that.

build-c2pa-archives.sh verifies and copies each archive as it builds so a
failure part-way still leaves the successful archives for the run
artifact, and clears target/artifacts first because a restored cargo
cache can carry archives from an older version. The four Android triples
now live in one sourced file shared with the release preflight.

track-c2pa-rs.yml gains mode: main. Resolve reads the upstream commit
instead of a release and skips the asset preflight; the marker is
`c2pa-track: <main sha> main@<upstream sha>` and the branch commit is an
empty marker commit. Sync installs stable Rust, fetches the single
commit, restores a cargo cache keyed on the upstream workspace, builds
the archives, and tests against them.

Because the Android gate is already split in two, main mode reports three
failure classes rather than two: capi-failure when the C API does not
compile for a target, build-failure when it does but the JNI bridge no
longer compiles against the new c2pa.h, and failure when both build and
the tests break. The archives are uploaded on red so a break can be
debugged without a full rebuild. Stable and rc are unchanged. The new
caller runs daily rather than on push, since the stable tracker already
covers our own main moving.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@scouten-adobe scouten-adobe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll approve, but there are a few things (esp. the first three) that I'd like you to at least consider:

  1. [High] Full test matrix duplicated on every main push — the stable tracker's matrix job reruns the entire emulator suite on essentially every commit to main, doubling CI cost indefinitely, because it never checks whether the resolved version actually changed.
  2. [High] promote can reopen spurious empty-diff PRs — after a promotion PR merges, the next push to main can trigger a brand-new "Update core C2PA SDK" PR with nothing to merge, since promote only checks the tracking branch's pin, not main's.
  3. [High] Infra failures mislabeled as FFI build breaksRecord Outcome's != "success" checks also match "skipped", so an unrelated early failure (checkout, SDK setup) gets diagnosed in the filed issue as "the JNI bridge no longer compiles against c2pa.h."
  4. [Medium] Unguarded nested resolve call in rc mode can abort the whole resolve job under set -e if no stable release exists to floor against.
  5. [Medium] Issue dedup uses the eventually-consistent GitHub Search API, risking duplicate tracking issues on closely-spaced runs.
  6. [Medium] Android target list triplicated (script, Gradle map, comments) with no automated drift check.
  7. [Low] previous_target computed but always empty for stable/rc — dead plumbing from a marker regex that only matches main-mode.

redaranj and others added 2 commits September 4, 2026 17:20
Seven findings from review of the tracking-branch workflows. The first two
share a root cause: nothing compared the resolved version against the
version main is already pinned to.

The idempotence guard keys on (main SHA, version), and the main SHA changes
on every push to main, so the guard could never skip there. When the
resolved version already equalled main's pin the rewrite was a no-op and the
branch was main plus an empty marker commit -- content-identical to main --
yet the full emulator matrix ran anyway, repeating the suite test.yml had
just run on the same push. On the first push after a promotion PR merged,
promote then found no open PR for the branch and opened a fresh one whose
only content was that empty commit. Resolve now publishes main's pin as an
output and both jobs are gated on the version actually moving. Sync still
runs, so the branch keeps tracking main as designed.

Record Outcome diagnosed failures with `!= success`, which also matches a
step that never ran. An unrelated early failure -- checkout, SDK setup --
left the AAR step skipped and was reported to a human as the JNI bridge no
longer compiling against c2pa.h. Every check is now an equality test against
`failure`, with a new infra-failure class for steps that were skipped
because something else died. That class also overrides the mode-based
urgency line, which would otherwise open a stable-tracker issue with
"main cannot move to this version" about a version never tested.

In rc mode the nested stable resolve was a bare command substitution under
set -e, so exit 3 killed the job and report-resolve-failure blamed the asset
preflight for a non-error. It now uses the same guarded form as the main
resolve and treats a missing stable release as nothing to track.

Issue dedup went through the code-search index, which is only eventually
consistent, so a run could miss an issue filed moments earlier and open a
duplicate. It now filters the label-scoped list endpoint client-side.

The target triples in c2pa-android-targets.sh and the architectures map in
build.gradle.kts had no drift check; check-target-drift.sh compares them and
runs in the lint job. previous_target was computed for every mode but its
marker regex only matches main mode, so it is now scoped to main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@redaranj
redaranj merged commit 3087aa4 into main Sep 8, 2026
9 checks passed
@redaranj
redaranj deleted the ci/c2pa-rs-tracking-branches branch September 8, 2026 07:00
@redaranj

redaranj commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

@scouten-adobe I addressed the issues you found on the Android tracking-branch PR and merged. I will apply a similar set of fixes on the Swift side.

redaranj added a commit to contentauth/c2pa-swift that referenced this pull request Sep 16, 2026
Seven findings from review of the Android port of these workflows
(contentauth/c2pa-android#131), six of which exist verbatim here because
the Android implementation was ported from this one. The first two share
a root cause: nothing compared the resolved version against the version
main is already pinned to.

The idempotence guard keys on (main SHA, version), and the main SHA changes
on every push to main, so the guard could never skip there. When the
resolved version already equalled main's pin the xcconfig rewrite was a
no-op and the branch was main plus an empty marker commit -- content-
identical to main -- yet the full simulator matrix ran anyway, repeating
the suite test.yml had just run on the same push, on macOS runners. On the
first push after a promotion PR merged, promote then found no open PR for
the branch and opened a fresh one whose only content was that empty
commit. Resolve now publishes main's pin as an output and both jobs are
gated on the version actually moving. Sync still runs, so the branch keeps
tracking main as designed.

Record Outcome diagnosed failures with `!= success`, which also matches a
step that never ran. An unrelated early failure -- checkout, Xcode setup
-- left the test step skipped and was reported to a human as a build or
test break against upstream. Every check is now an equality test against
`failure`, with a new infra-failure class for a test step that was skipped
because something else died. That class also overrides the mode-based
urgency line, which would otherwise open a stable-tracker issue with
"main cannot move to this version" about a version never tested.

In rc mode the nested stable resolve was a bare command substitution under
set -e, so exit 3 killed the job and report-resolve-failure blamed the
asset preflight for a non-error. It now uses the same guarded form as the
main resolve and treats a missing stable release as nothing to track.

Issue dedup went through the code-search index, which is only eventually
consistent, so a run could miss an issue filed moments earlier and open a
duplicate. It now filters the label-scoped list endpoint client-side.

The target triples in c2pa-apple-targets.sh and the *_SUFFIX assignments
in the C2PAC build phase had no drift check; check-target-drift.sh reads
the suffixes out of the shell script embedded in the pbxproj, compares the
two lists, and runs in the lint job. previous_target was computed for
every mode but its marker regex only matches main mode, so it is now
scoped to main.

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants