* ci(release): explain App Store 'previous version in review' failures
When a release is tagged before the previous version clears Apple review,
App Store Connect refuses to create the version or attach the build, and
the lane died with a raw spaceship stacktrace ('cannot create a new
version...' / 'pre-release build could not be added'). Both hit v18.13.1
(iOS + macOS) and v18.12.1 (macOS).
Match those two messages and replace the stacktrace with a one-line,
actionable annotation (let the previous version finish review, or pull it
from review, then re-run) -- still a hard failure, since the version did
not go out and a green run would falsely read as 'released'. The existing
'review submission already in progress' race stays a soft success.
Static annotation text only (no e/options interpolation; key-material).
* fix(sync): name discarded title in LWW conflict banner; fix fr dismiss label (#8694)
* fix(sync): surface the last discarded title in LWW conflict banner
Multi-review follow-up to the #8694 banner:
- Show the LAST non-empty discarded title (the user's final offline rename),
not the first — a stale intermediate rename is misleading. Also simpler
(drops the first-wins guard).
- Document why the kept==discarded equality guard is correct: when a title
edit loses to a concurrent other-field remote win, the current state still
shows the rejected local title, so an annotation would only repeat it —
silencing it is right, not a hidden divergence.
fr.json G.DISMISS "Rejeter"->"Ignorer" (prior commit) is an intentional,
owner-approved deviation from the en-only rule: it is a mistranslation fix
for the shared banner dismiss label, not a new string. Other locales may
carry the same "Reject"-flavored label — left as a follow-up.
The iOS and macOS release lanes both run on a v* tag push and can race
on App Store Connect's per-app review-submission state. When they
collide, the lane that submits second fails with 'A review submission is
already in progress' -- but only after its binary has already uploaded
and processed successfully, so the build is safe.
Route both lanes through a shared submit_to_app_store helper that treats
that one collision as a soft success and emits a GitHub Actions warning
annotation so the required manual step (add the build to the open
submission) stays visible on a green run. Every other failure, and any
failure before upload (e.g. the version-creation race), still aborts the
lane loudly.
* fix(build): keep @electron/asar on minimatch v3 for MAS universal build
The `overrides.app-builder-lib.minimatch` pin to v10 cascaded into
@electron/asar (a child of both app-builder-lib and @electron/universal),
which only works with minimatch v3. minimatch v9/v10 ship as ESM with
`__esModule: true` and no `default` export, so @electron/asar's compiled
default import (`minimatch_1.default(...)`) resolved to undefined and threw
`TypeError: (0 , minimatch_1.default) is not a function` during the
universal-app asar merge (makeUniversalApp -> mergeASARs -> shouldUnpackPath),
failing `dist:mac:mas:buildOnly` in the Mac Store release workflow.
Carve @electron/asar back to minimatch 3.1.2 via nested overrides while
app-builder-lib (and @electron/universal) keep minimatch v10 as intended.
* fix(ci): declare export compliance for iOS App Store submission
The iOS release build, upload and processing all succeed, but
`upload_to_app_store` fails at submit-for-review with:
[!] Export compliance is required to submit
Example: submission_information: { export_compliance_uses_encryption: false }
Super Productivity only relies on exempt encryption (HTTPS / standard OS
crypto), so declare that the app does not use non-exempt encryption:
- ios/App/App/Info.plist: ITSAppUsesNonExemptEncryption=false (canonical,
build-time declaration; also covers TestFlight, auto-resolved by ASC).
- fastlane/Fastfile: export_compliance_uses_encryption: false in
submission_information, so the submit-for-review API call carries the
declaration regardless of the binary.
* refactor(build): simplify @electron/asar minimatch override to top-level
Follow-up to the minimatch carve-out. Hoisting a top-level
`overrides["@electron/asar"].minimatch` pin produces a byte-identical
package-lock.json to the previous nested form, but is simpler and covers
every @electron/asar consumer (app-builder-lib, @electron/universal,
electron-winstaller) regardless of which parent wins hoisting — rather than
relying on a nested branch under app-builder-lib (whose @electron/universal
sub-branch was dead config given asar dedupes to a single instance).
* test(op-log): de-flake LockService mutex-invariant timeout test
"should preserve mutex invariant after timeout" flaked on the macOS CI
runner (TZ=America/Los_Angeles leg): it asserted that C always times out
waiting for the lock, but on a slow/loaded runner A can release the lock
before C's 50ms timeout fires, so C legitimately acquires it and runs —
after A has finished. The observed `['a-start','a-end','c-start']` actually
satisfies the invariant (C ran after A, never concurrently); only the
brittle "C must time out" assertion failed.
Assert the real no-concurrent-execution invariant instead: C must never
start before A ends. This still catches the original regression (concurrent
C would push 'c-start' before 'a-end') but is independent of runner timing.
---------
Co-authored-by: Claude <noreply@anthropic.com>
* ci: auto-submit iOS and macOS App Store builds for review
The iOS and Mac App Store workflows previously stopped after uploading the
build to App Store Connect via altool, leaving version creation, "What's New"
and submission as manual steps.
Add fastlane lanes (ios/mac release) that upload the prebuilt .ipa / MAS .pkg
using App Store Connect API key auth (reusing the existing notarization key
secrets), push release notes derived from build/release-notes.md, wait for
processing, submit for review and flag automatic release on approval.
Final version tags submit for review; pre-release tags (RC/beta/alpha) and
manual runs only upload the build. Listing metadata and screenshots remain
curated by hand in App Store Connect.
https://claude.ai/code/session_014c1W1mX7tfvFzpZ6wyWzsJ
* ci: wire iOS and Mac Store workflows to fastlane submit lane
The previous commit added the fastlane lanes but the workflow edits were not
applied. Replace the altool validate/upload steps in the iOS and Mac App Store
workflows with the fastlane submit lane: install fastlane, generate the App
Store "What's New" notes and run `fastlane <platform> release` with App Store
Connect API key auth.
Also extend the Mac workflow's harden-runner egress allowlist with the
rubygems and App Store Connect endpoints used by fastlane.
https://claude.ai/code/session_014c1W1mX7tfvFzpZ6wyWzsJ
* fix(ci): harden Apple App Store auto-submission after review
Address review findings on the iOS/macOS App Store automation:
- Tag gating: submit only when the tag has no "-" (final semver), instead of
denylisting RC/beta/alpha. GitHub Actions contains() is case-sensitive and
the repo's RC tags are mostly lowercase (-rc.N), so the old guard would have
auto-submitted release candidates to production review.
- Fastfile: set skip_metadata so deliver no longer reads back and re-uploads
curated listing fields; push only "What's New" via an inline release_notes
hash. Warn against verbose mode (can dump the API key).
- Gemfile.lock: add arm64-darwin/x86_64-darwin platforms so bundle install
works on the macOS runners.
- Workflows: install deps via pinned ruby/setup-ruby (bundler cache), and
resolve the artifact path with a strict nullglob check (exactly one match)
instead of ls | head.
- release-notes script: tighten emphasis regexes so stray * / _ (globs,
snake_case) survive, anchor footer patterns so legitimate "download" lines
are not dropped, and drop a duplicate mkdir.
- Docs: document the hyphen-based gate, single-use build numbers, automatic
release behavior and inline validation.
https://claude.ai/code/session_014c1W1mX7tfvFzpZ6wyWzsJ
* fix(ci): correct deliver metadata + setup-ruby version (second review pass)
Two bugs introduced by the previous review-fix commit, both confirmed against
upstream source:
- Fastfile: skip_metadata: true makes deliver's upload_metadata return early
(verified in fastlane 2.225.0 deliver/lib/deliver/upload_metadata.rb), so the
"What's New" notes were never uploaded. Revert to metadata_path pointing at a
dir that contains only <locale>/release_notes.txt; load_from_filesystem reads
only that file (next unless File.exist?) with no remote read-back, so other
listing fields stay untouched. Removed the now-unused inline release_notes
helper.
- Workflows: ruby/setup-ruby throws when ruby-version is unset and no
.ruby-version file exists (it does not fall back to system Ruby). Pin
ruby-version: '3.3' in both workflows.
Docs updated to match the corrected metadata approach.
https://claude.ai/code/session_014c1W1mX7tfvFzpZ6wyWzsJ
* fix(ci): remove invalid wait_for_uploaded_build from deliver lanes
wait_for_uploaded_build is a pilot/upload_to_testflight option, not a deliver one. Passing it to upload_to_app_store makes fastlane raise on the unknown key and fail both iOS and macOS release lanes on every run. deliver already waits for the build to finish processing during submit (select_build -> wait_for_build_processing_to_be_complete), so no replacement is needed.
Also pin the ruby/setup-ruby comment to its resolved version (v1.310.0), and slice the App Store release notes by code point so a multi-byte character is never split at the 4000-char cap.
---------
Co-authored-by: Claude <noreply@anthropic.com>
Relocate fastlane metadata from root to android/fastlane where it belongs for Android projects. Update bump-android-version.js script to use the new path.