mirror of
https://github.com/johannesjo/super-productivity.git
synced 2026-07-18 08:56:41 +00:00
* 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>
96 lines
4.2 KiB
Ruby
96 lines
4.2 KiB
Ruby
# iOS and macOS App Store submission lanes.
|
|
#
|
|
# The signed release binaries are produced in CI:
|
|
# - iOS: .github/workflows/build-ios.yml -> .ipa
|
|
# - macOS: .github/workflows/build-publish-to-mac-store-on-release.yml -> MAS .pkg
|
|
#
|
|
# These lanes take the finished artifact, upload it to App Store Connect, set
|
|
# the "What's New" text, submit the version for review and flag it to be
|
|
# released automatically once Apple approves it. The only step that cannot be
|
|
# automated is Apple's human review itself.
|
|
#
|
|
# Authentication uses an App Store Connect API key (not an Apple ID +
|
|
# app-specific password), which is far more robust in CI.
|
|
#
|
|
# IMPORTANT: the API key must belong to a user with the "App Manager" role (or
|
|
# higher). A key with only the "Developer" role can upload/notarize but cannot
|
|
# create a version or submit it for review.
|
|
#
|
|
# SECURITY: never enable verbose mode (--verbose / FASTLANE_VERBOSE / verbose:
|
|
# true) in these lanes. Verbose output can dump the deliver options hash, which
|
|
# contains the App Store Connect API key material.
|
|
#
|
|
# Listing metadata (description, keywords, screenshots, ...) is managed manually
|
|
# in App Store Connect and is intentionally NOT overwritten here. METADATA_PATH
|
|
# is a dedicated dir that contains ONLY <locale>/release_notes.txt, so deliver's
|
|
# load_from_filesystem reads just the release notes (it skips fields with no
|
|
# local file: `next unless File.exist?`, and upload skips nil fields). There is
|
|
# no remote read-back, so other listing fields are left untouched. Do NOT set
|
|
# `skip_metadata` here: it makes deliver return early and upload no release notes
|
|
# at all. `skip_screenshots` is safe — screenshots live elsewhere.
|
|
#
|
|
# Required env vars (wired from GitHub secrets in the workflows):
|
|
# ASC_KEY_ID App Store Connect API key id (secrets.mac_api_key_id)
|
|
# ASC_ISSUER_ID App Store Connect API issuer id (secrets.mac_api_key_issuer_id)
|
|
# ASC_KEY_CONTENT Contents of the .p8 key file (secrets.mac_api_key)
|
|
# IPA_PATH Path to the built .ipa (ios lane)
|
|
# PKG_PATH Path to the built MAS .pkg (mac lane)
|
|
# Optional:
|
|
# METADATA_PATH release-notes dir (default: fastlane/appstore_metadata)
|
|
# SUBMIT_FOR_REVIEW "false" to only upload the build without submitting
|
|
|
|
APP_IDENTIFIER = 'com.super-productivity.app'
|
|
|
|
def asc_api_key
|
|
app_store_connect_api_key(
|
|
key_id: ENV.fetch('ASC_KEY_ID'),
|
|
issuer_id: ENV.fetch('ASC_ISSUER_ID'),
|
|
key_content: ENV.fetch('ASC_KEY_CONTENT'),
|
|
is_key_content_base64: false,
|
|
)
|
|
end
|
|
|
|
def submit_for_review?
|
|
ENV.fetch('SUBMIT_FOR_REVIEW', 'true') != 'false'
|
|
end
|
|
|
|
# Shared deliver options. `extra` carries the platform-specific binary path.
|
|
def deliver_options(extra)
|
|
{
|
|
api_key: asc_api_key,
|
|
app_identifier: APP_IDENTIFIER,
|
|
# Dir holding only <locale>/release_notes.txt -> deliver uploads just the
|
|
# "What's New" text and leaves every other listing field as-is. (Do not add
|
|
# skip_metadata; see the header comment.)
|
|
metadata_path: ENV.fetch('METADATA_PATH', 'fastlane/appstore_metadata'),
|
|
skip_screenshots: true,
|
|
submit_for_review: submit_for_review?,
|
|
automatic_release: true,
|
|
# Precheck inspects listing metadata we don't manage from here.
|
|
run_precheck_before_submit: false,
|
|
submission_information: {
|
|
add_id_info_uses_idfa: false,
|
|
# The app only relies on exempt encryption (HTTPS/standard OS crypto), so
|
|
# it does not use non-exempt encryption. Without this, App Store Connect
|
|
# rejects the submission with "Export compliance is required to submit".
|
|
# Mirrors ITSAppUsesNonExemptEncryption=false in ios/App/App/Info.plist.
|
|
export_compliance_uses_encryption: false,
|
|
},
|
|
# Non-interactive: skip the HTML report confirmation prompt.
|
|
force: true,
|
|
}.merge(extra)
|
|
end
|
|
|
|
platform :ios do
|
|
desc 'Upload the prebuilt iOS .ipa to App Store Connect and submit for review'
|
|
lane :release do
|
|
upload_to_app_store(deliver_options(platform: 'ios', ipa: ENV.fetch('IPA_PATH')))
|
|
end
|
|
end
|
|
|
|
platform :mac do
|
|
desc 'Upload the prebuilt macOS .pkg to App Store Connect and submit for review'
|
|
lane :release do
|
|
upload_to_app_store(deliver_options(platform: 'osx', pkg: ENV.fetch('PKG_PATH')))
|
|
end
|
|
end
|