release: sign 1.1.3 without notarization
This commit is contained in:
@@ -1,19 +1,12 @@
|
|||||||
name: Finalize Release
|
name: Finalize Notarization (manual)
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_run:
|
|
||||||
workflows:
|
|
||||||
- Release
|
|
||||||
types:
|
|
||||||
- completed
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
release_run_id:
|
release_run_id:
|
||||||
description: Release workflow run ID; leave blank to use the latest pending run
|
description: Release workflow run ID; leave blank to use the latest pending run
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
schedule:
|
|
||||||
- cron: "17,47 * * * *"
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
actions: read
|
actions: read
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: write
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: meetingnotes-release
|
group: meetingnotes-release
|
||||||
@@ -20,9 +20,7 @@ jobs:
|
|||||||
runs-on: macos-15
|
runs-on: macos-15
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ inputs.version }}
|
VERSION: ${{ inputs.version }}
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
with:
|
with:
|
||||||
@@ -33,7 +31,7 @@ jobs:
|
|||||||
APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
|
APPLE_CERTIFICATE_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
||||||
run: |
|
run: |
|
||||||
for variable in APPLE_CERTIFICATE_P12 APPLE_CERTIFICATE_PASSWORD APPLE_ID APPLE_TEAM_ID APPLE_APP_PASSWORD; do
|
for variable in APPLE_CERTIFICATE_P12 APPLE_CERTIFICATE_PASSWORD SPARKLE_PRIVATE_KEY; do
|
||||||
if [[ -z "${!variable:-}" ]]; then
|
if [[ -z "${!variable:-}" ]]; then
|
||||||
echo "Missing GitHub Actions secret: $variable" >&2
|
echo "Missing GitHub Actions secret: $variable" >&2
|
||||||
exit 1
|
exit 1
|
||||||
@@ -55,20 +53,19 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
echo "SIGNING_IDENTITY=$signing_identity" >> "$GITHUB_ENV"
|
echo "SIGNING_IDENTITY=$signing_identity" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
- name: Build, sign, and submit for notarization
|
- name: Build and sign release
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
run: scripts/package_release.sh
|
run: scripts/package_release.sh
|
||||||
|
|
||||||
- name: Preserve signed build while Apple processes it
|
- name: Preserve signed release artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: meetingnotes-notarization-${{ github.run_id }}
|
name: meetingnotes-signed-release-${{ github.run_id }}
|
||||||
path: ${{ runner.temp }}/meetingnotes-release/pending
|
path: ${{ runner.temp }}/meetingnotes-release/release
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
- name: Legacy inline publisher (disabled)
|
- name: Publish signed GitHub release
|
||||||
if: ${{ false }}
|
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -278,7 +278,7 @@
|
|||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 15;
|
CURRENT_PROJECT_VERSION = 15;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = ML6HYR5LUR;
|
DEVELOPMENT_TEAM = G9LVHZAJNX;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
MARKETING_VERSION = 1.1.3;
|
MARKETING_VERSION = 1.1.3;
|
||||||
ONLY_ACTIVE_ARCH = NO;
|
ONLY_ACTIVE_ARCH = NO;
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_TCC_SPI";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_TCC_SPI";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = owen.meetingnotes;
|
PRODUCT_BUNDLE_IDENTIFIER = net.jamesbone.meetingnotes;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
@@ -314,7 +314,7 @@
|
|||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 15;
|
CURRENT_PROJECT_VERSION = 15;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"meetingnotes/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = ML6HYR5LUR;
|
DEVELOPMENT_TEAM = G9LVHZAJNX;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
@@ -329,7 +329,7 @@
|
|||||||
MARKETING_VERSION = 1.1.3;
|
MARKETING_VERSION = 1.1.3;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_TCC_SPI";
|
OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_TCC_SPI";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = owen.meetingnotes;
|
PRODUCT_BUNDLE_IDENTIFIER = net.jamesbone.meetingnotes;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import Security
|
|||||||
class KeychainHelper {
|
class KeychainHelper {
|
||||||
static let shared = KeychainHelper()
|
static let shared = KeychainHelper()
|
||||||
|
|
||||||
private let serviceName = "owen.meetingnotes"
|
private let serviceName = "net.jamesbone.meetingnotes"
|
||||||
|
|
||||||
private init() {}
|
private init() {}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ extension String: @retroactive LocalizedError {
|
|||||||
@Observable
|
@Observable
|
||||||
final class AudioProcessController {
|
final class AudioProcessController {
|
||||||
|
|
||||||
private let logger = Logger(subsystem: "owen.meetingnotes", category: String(describing: AudioProcessController.self))
|
private let logger = Logger(subsystem: "net.jamesbone.meetingnotes", category: String(describing: AudioProcessController.self))
|
||||||
|
|
||||||
private(set) var processes = [AudioProcess]() {
|
private(set) var processes = [AudioProcess]() {
|
||||||
didSet {
|
didSet {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import OSLog
|
|||||||
/// Uses TCC SPI in order to check/request system audio recording permission.
|
/// Uses TCC SPI in order to check/request system audio recording permission.
|
||||||
@Observable
|
@Observable
|
||||||
final class AudioRecordingPermission {
|
final class AudioRecordingPermission {
|
||||||
private let logger = Logger(subsystem: "owen.meetingnotes", category: String(describing: AudioRecordingPermission.self))
|
private let logger = Logger(subsystem: "net.jamesbone.meetingnotes", category: String(describing: AudioRecordingPermission.self))
|
||||||
|
|
||||||
enum Status: String {
|
enum Status: String {
|
||||||
case unknown
|
case unknown
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ final class ProcessTap {
|
|||||||
init(target: TapTarget, muteWhenRunning: Bool = false) {
|
init(target: TapTarget, muteWhenRunning: Bool = false) {
|
||||||
self.target = target
|
self.target = target
|
||||||
self.muteWhenRunning = muteWhenRunning
|
self.muteWhenRunning = muteWhenRunning
|
||||||
self.logger = Logger(subsystem: "owen.meetingnotes", category: "\(String(describing: ProcessTap.self))(\(target.loggingProcessName))")
|
self.logger = Logger(subsystem: "net.jamesbone.meetingnotes", category: "\(String(describing: ProcessTap.self))(\(target.loggingProcessName))")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ObservationIgnored
|
@ObservationIgnored
|
||||||
@@ -327,7 +327,7 @@ final class ProcessTapRecorder {
|
|||||||
self.tapDisplayName = tap.displayName
|
self.tapDisplayName = tap.displayName
|
||||||
self.fileURL = fileURL
|
self.fileURL = fileURL
|
||||||
self._tap = tap
|
self._tap = tap
|
||||||
self.logger = Logger(subsystem: "owen.meetingnotes", category: "\(String(describing: ProcessTapRecorder.self))(\(fileURL.lastPathComponent))")
|
self.logger = Logger(subsystem: "net.jamesbone.meetingnotes", category: "\(String(describing: ProcessTapRecorder.self))(\(fileURL.lastPathComponent))")
|
||||||
|
|
||||||
self.icon = tap.target.iconImage
|
self.icon = tap.target.iconImage
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
|
<key>com.apple.security.temporary-exception.mach-lookup.global-name</key>
|
||||||
<array>
|
<array>
|
||||||
<string>owen.meetingnotes-spks</string>
|
<string>net.jamesbone.meetingnotes-spks</string>
|
||||||
<string>owen.meetingnotes-spki</string>
|
<string>net.jamesbone.meetingnotes-spki</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ set -e # Exit on any error
|
|||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
APP_NAME="Meetingnotes"
|
APP_NAME="Meetingnotes"
|
||||||
BUNDLE_ID="owen.meetingnotes"
|
BUNDLE_ID="net.jamesbone.meetingnotes"
|
||||||
VERSION=$(grep -m1 "MARKETING_VERSION" Meetingnotes.xcodeproj/project.pbxproj | sed 's/.*= \(.*\);/\1/')
|
VERSION=$(grep -m1 "MARKETING_VERSION" Meetingnotes.xcodeproj/project.pbxproj | sed 's/.*= \(.*\);/\1/')
|
||||||
|
|
||||||
# Source environment variables if .env file exists
|
# Source environment variables if .env file exists
|
||||||
|
|||||||
+19
-23
@@ -8,16 +8,14 @@ SCHEME="meetingnotes"
|
|||||||
RUNNER_TEMP="${RUNNER_TEMP:-/tmp}"
|
RUNNER_TEMP="${RUNNER_TEMP:-/tmp}"
|
||||||
BUILD_ROOT="${BUILD_ROOT:-$RUNNER_TEMP/meetingnotes-release}"
|
BUILD_ROOT="${BUILD_ROOT:-$RUNNER_TEMP/meetingnotes-release}"
|
||||||
DERIVED_DATA="$BUILD_ROOT/DerivedData"
|
DERIVED_DATA="$BUILD_ROOT/DerivedData"
|
||||||
PENDING_DIR="$BUILD_ROOT/pending"
|
RELEASE_DIR="$BUILD_ROOT/release"
|
||||||
APP_PATH="$DERIVED_DATA/Build/Products/Release/$APP_NAME.app"
|
APP_PATH="$DERIVED_DATA/Build/Products/Release/$APP_NAME.app"
|
||||||
|
|
||||||
required_variables=(
|
required_variables=(
|
||||||
VERSION
|
VERSION
|
||||||
SIGNING_IDENTITY
|
SIGNING_IDENTITY
|
||||||
APPLE_ID
|
SPARKLE_PRIVATE_KEY
|
||||||
APPLE_TEAM_ID
|
GITHUB_REPOSITORY
|
||||||
APPLE_APP_PASSWORD
|
|
||||||
GITHUB_SHA
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for variable in "${required_variables[@]}"; do
|
for variable in "${required_variables[@]}"; do
|
||||||
@@ -34,7 +32,7 @@ if [[ "$project_version" != "$VERSION" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf "$BUILD_ROOT"
|
rm -rf "$BUILD_ROOT"
|
||||||
mkdir -p "$PENDING_DIR"
|
mkdir -p "$RELEASE_DIR"
|
||||||
|
|
||||||
xcodebuild \
|
xcodebuild \
|
||||||
-project "$PROJECT" \
|
-project "$PROJECT" \
|
||||||
@@ -78,31 +76,29 @@ codesign --force --timestamp --options runtime \
|
|||||||
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
|
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
|
||||||
codesign -d --entitlements :- "$APP_PATH" 2>&1 | grep -q 'com.apple.security.app-sandbox'
|
codesign -d --entitlements :- "$APP_PATH" 2>&1 | grep -q 'com.apple.security.app-sandbox'
|
||||||
|
|
||||||
PRE_NOTARY_ZIP="$PENDING_DIR/$APP_NAME-pre-notary.zip"
|
ARCHIVE_NAME="$APP_NAME-$VERSION.zip"
|
||||||
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$PRE_NOTARY_ZIP"
|
ARCHIVE_PATH="$RELEASE_DIR/$ARCHIVE_NAME"
|
||||||
|
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$ARCHIVE_PATH"
|
||||||
xcrun notarytool submit "$PRE_NOTARY_ZIP" \
|
|
||||||
--apple-id "$APPLE_ID" \
|
|
||||||
--team-id "$APPLE_TEAM_ID" \
|
|
||||||
--password "$APPLE_APP_PASSWORD" \
|
|
||||||
--output-format json > "$PENDING_DIR/notary-submission.json"
|
|
||||||
|
|
||||||
SUBMISSION_ID=$(plutil -extract id raw -o - "$PENDING_DIR/notary-submission.json")
|
|
||||||
echo "Notarization submitted: $SUBMISSION_ID"
|
|
||||||
|
|
||||||
GENERATE_APPCAST=$(find "$DERIVED_DATA/SourcePackages/artifacts" -type f -name generate_appcast -print -quit)
|
GENERATE_APPCAST=$(find "$DERIVED_DATA/SourcePackages/artifacts" -type f -name generate_appcast -print -quit)
|
||||||
if [[ -z "$GENERATE_APPCAST" ]]; then
|
if [[ -z "$GENERATE_APPCAST" ]]; then
|
||||||
echo "Sparkle generate_appcast tool was not found" >&2
|
echo "Sparkle generate_appcast tool was not found" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
cp "$GENERATE_APPCAST" "$PENDING_DIR/generate_appcast"
|
|
||||||
|
|
||||||
printf '%s' "$VERSION" > "$PENDING_DIR/version"
|
DOWNLOAD_URL="https://github.com/$GITHUB_REPOSITORY/releases/download/v$VERSION/"
|
||||||
printf '%s' "$GITHUB_SHA" > "$PENDING_DIR/commit-sha"
|
printf '%s' "$SPARKLE_PRIVATE_KEY" | "$GENERATE_APPCAST" "$RELEASE_DIR" \
|
||||||
|
--ed-key-file - \
|
||||||
|
--download-url-prefix "$DOWNLOAD_URL" \
|
||||||
|
--maximum-deltas 0 \
|
||||||
|
-o "$RELEASE_DIR/appcast.xml"
|
||||||
|
|
||||||
|
grep -q "$DOWNLOAD_URL$ARCHIVE_NAME" "$RELEASE_DIR/appcast.xml"
|
||||||
|
grep -q 'sparkle:edSignature=' "$RELEASE_DIR/appcast.xml"
|
||||||
|
|
||||||
if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
|
if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
|
||||||
printf 'Submitted Meetingnotes %s for Apple notarization.\n\nSubmission: `%s`\n\nThe finalize workflow will publish the release after Apple accepts it.\n' \
|
printf 'Built and Developer ID-signed Meetingnotes %s. The GitHub release is ready to publish.\n' \
|
||||||
"$VERSION" "$SUBMISSION_ID" >> "$GITHUB_STEP_SUMMARY"
|
"$VERSION" >> "$GITHUB_STEP_SUMMARY"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Signed app and notarization metadata are ready in $PENDING_DIR"
|
echo "Signed release artifacts are ready in $RELEASE_DIR"
|
||||||
|
|||||||
Reference in New Issue
Block a user