Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/github.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@
"release or signing changes"
]
},
"importantWorkflows": ["CI", "CodeQL", "Release", "TestFlight"],
"importantWorkflows": [
"CI",
"CodeQL",
"Release",
"TestFlight",
"Submit App Store Review"
],
"branchProtection": {
"ruleset": {
"name": "Protect main",
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/submit-app-store-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
name: Submit App Store Review

"on":
workflow_dispatch:
inputs:
version:
description: App Store marketing version.
required: true
type: string
build_number:
description: Uploaded CFBundleVersion/build number.
required: true
type: string
whats_new:
description: Release notes for the App Store version.
required: true
type: string
copy_from_version:
description: Existing App Store version to copy metadata from.
required: false
type: string
dry_run:
description: Prepare the version and review item without submitting.
required: true
default: false
type: boolean

permissions:
contents: read

concurrency:
group: submit-app-store-review-${{ github.event.inputs.version }}
cancel-in-progress: false

jobs:
submit:
name: Submit App Store Review
runs-on: macos-latest

env:
APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }}
APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY_P8_BASE64: >-
${{ secrets.APP_STORE_CONNECT_API_KEY_P8_BASE64 }}

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Install Python Dependencies
run: python3 -m pip install --user cryptography

- name: Submit Review
shell: bash
run: |
set -euo pipefail
args=(
--version "${{ inputs.version }}"
--build-number "${{ inputs.build_number }}"
--whats-new "${{ inputs.whats_new }}"
)
if [[ -n "${{ inputs.copy_from_version }}" ]]; then
args+=(--copy-from-version "${{ inputs.copy_from_version }}")
fi
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
args+=(--dry-run)
fi
scripts/submit-app-store-review.py "${args[@]}"
20 changes: 20 additions & 0 deletions docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,26 @@ Xcode project, installs the supplied provisioning profiles, archives with manual
but cannot be selected for App Store submission. Pass `upload: false` when
dispatching the workflow to export the `.pkg` without uploading it.

After the uploaded build is processed, run the `Submit App Store Review` workflow
with the App Store marketing version, uploaded build number, and App Store
release notes. The workflow calls `scripts/submit-app-store-review.py`, which
creates or reuses the Mac App Store version, attaches the validated build,
copies localization and review-contact metadata from an existing version, updates
`What's New`, and submits the review submission. Use `dry_run: true` to create
or update the version and review-submission item without pressing the API submit
step.

For local operator use, the same script accepts an API key path or the existing
App Store Connect environment variables:

```sh
scripts/submit-app-store-review.py \
--version 1.0.12 \
--build-number 202605290049 \
--copy-from-version 1.0.2 \
--whats-new "Improves multi-account provider identity handling."
```

The app and refresh-agent App Store entitlements must keep the sandbox enabled
with App Group, outbound network, read-only user-selected file access, and
app-scope bookmark permissions. The widget should keep only the sandbox and App
Expand Down
Loading