Skip to content

fix(windows): FIN/RST on a direct flow now actually clears the port d… #346

fix(windows): FIN/RST on a direct flow now actually clears the port d…

fix(windows): FIN/RST on a direct flow now actually clears the port d… #346

Workflow file for this run

name: Build macOS
permissions:
contents: read
on:
push:
branches: [ dev, main, master ]
pull_request:
branches: [ dev, main, master ]
workflow_dispatch:
jobs:
build:
runs-on: macos-latest
permissions:
contents: read
actions: read
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Set up Xcode
uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1
with:
xcode-version: latest-stable
- name: Create xcconfig files
run: |
echo "${{ secrets.MACOS_APP_XCCONFIG }}" > MacOS/ProxyBridge/Signing-Config-app.xcconfig
echo "${{ secrets.MACOS_EXT_XCCONFIG }}" > MacOS/ProxyBridge/Signing-Config-ext.xcconfig
- name: Install Provisioning Profiles
run: |
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo "${{ secrets.MACOS_APP_PROVISION_PROFILE }}" | base64 --decode > /tmp/app.provisionprofile
echo "${{ secrets.MACOS_EXT_PROVISION_PROFILE }}" | base64 --decode > /tmp/ext.provisionprofile
APP_UUID=$(security cms -D -i /tmp/app.provisionprofile | plutil -extract UUID raw -)
EXT_UUID=$(security cms -D -i /tmp/ext.provisionprofile | plutil -extract UUID raw -)
cp /tmp/app.provisionprofile ~/Library/MobileDevice/Provisioning\ Profiles/${APP_UUID}.provisionprofile
cp /tmp/ext.provisionprofile ~/Library/MobileDevice/Provisioning\ Profiles/${EXT_UUID}.provisionprofile
echo "Installed app profile: ${APP_UUID}"
echo "Installed ext profile: ${EXT_UUID}"
- name: Import Certificate
run: |
# Decode certificate
echo "${{ secrets.MACOS_CERTIFICATE }}" | base64 --decode > /tmp/certificate.p12
# Create a temporary keychain
security create-keychain -p "${{ secrets.MACOS_KEYCHAIN_PASSWORD }}" build.keychain
security default-keychain -s build.keychain
security unlock-keychain -p "${{ secrets.MACOS_KEYCHAIN_PASSWORD }}" build.keychain
security set-keychain-settings build.keychain
# Import Developer ID Application certificate
security import /tmp/certificate.p12 \
-k build.keychain \
-P "${{ secrets.MACOS_CERTIFICATE_PASSWORD }}" \
-T /usr/bin/codesign \
-A
# Import Developer ID Installer certificate
echo "${{ secrets.MACOS_INSTALLER_CERTIFICATE }}" | base64 --decode > /tmp/installer.p12
security import /tmp/installer.p12 \
-k build.keychain \
-P "${{ secrets.MACOS_INSTALLER_CERTIFICATE_PASSWORD }}" \
-T /usr/bin/codesign \
-T /usr/bin/productsign \
-A
# Allow codesign and productsign to access the keychain without prompting
security set-key-partition-list -S apple-tool:,apple: -s -k "${{ secrets.MACOS_KEYCHAIN_PASSWORD }}" build.keychain
# Add build.keychain to the keychain search list so productsign can find the cert
security list-keychains -d user -s build.keychain login.keychain-db
# Verify both certificates are available
security find-identity -v -p codesigning build.keychain
- name: Build Universal Binary
run: |
cd MacOS/ProxyBridge
xcodebuild \
-project ProxyBridge.xcodeproj \
-scheme ProxyBridge \
-configuration Release \
-derivedDataPath build/DerivedData \
ARCHS="arm64 x86_64" \
ONLY_ACTIVE_ARCH=NO \
OTHER_CODE_SIGN_FLAGS="--keychain build.keychain --timestamp" \
clean build
- name: Verify Build
run: |
cd MacOS/ProxyBridge
ls -la build/DerivedData/Build/Products/Release/
file build/DerivedData/Build/Products/Release/ProxyBridge.app/Contents/MacOS/ProxyBridge
lipo -archs build/DerivedData/Build/Products/Release/ProxyBridge.app/Contents/MacOS/ProxyBridge
# Verify code signature
codesign -dv --verbose=4 build/DerivedData/Build/Products/Release/ProxyBridge.app
- name: Notarize App
run: |
APP_PATH="MacOS/ProxyBridge/build/DerivedData/Build/Products/Release/ProxyBridge.app"
# Zip the app for submission
ditto -c -k --keepParent "$APP_PATH" /tmp/ProxyBridge.zip
# Submit for notarization and wait for result, capture submission ID
SUBMIT_OUTPUT=$(xcrun notarytool submit /tmp/ProxyBridge.zip \
--apple-id "${{ secrets.APPLE_ID }}" \
--password "${{ secrets.APPLE_APP_PASSWORD }}" \
--team-id "${{ secrets.APPLE_TEAM_ID }}" \
--wait 2>&1)
echo "$SUBMIT_OUTPUT"
# Extract submission ID
SUBMISSION_ID=$(echo "$SUBMIT_OUTPUT" | grep "^ id:" | head -1 | awk '{print $2}')
echo "Submission ID: $SUBMISSION_ID"
# Always fetch the detailed log from Apple
if [ -n "$SUBMISSION_ID" ]; then
echo "--- Notarization Log ---"
xcrun notarytool log "$SUBMISSION_ID" \
--apple-id "${{ secrets.APPLE_ID }}" \
--password "${{ secrets.APPLE_APP_PASSWORD }}" \
--team-id "${{ secrets.APPLE_TEAM_ID }}" 2>&1 || true
fi
# Fail if notarization was not accepted
if ! echo "$SUBMIT_OUTPUT" | grep -q "status: Accepted"; then
echo "Notarization failed!"
exit 1
fi
# Staple the notarization ticket to the app
xcrun stapler staple "$APP_PATH"
# Verify notarization
spctl -a -vvv -t install "$APP_PATH"
- name: Build PKG Installer
env:
PKG_ENV_CONTENT: ${{ secrets.PKG_ENV }}
run: |
# Write PKG_ENV to .env but strip SIGNING_IDENTITY so build.sh skips signing
# (productsign inside build.sh cannot access build.keychain - we do it below)
printf '%s' "$PKG_ENV_CONTENT" | grep -v "^SIGNING_IDENTITY" > MacOS/ProxyBridge/.env
# Copy notarized .app into output/ where build.sh expects it
mkdir -p MacOS/ProxyBridge/output
cp -R MacOS/ProxyBridge/build/DerivedData/Build/Products/Release/ProxyBridge.app \
MacOS/ProxyBridge/output/ProxyBridge.app
# Run build script - creates the unsigned .pkg only
cd MacOS/ProxyBridge
chmod +x build.sh
bash build.sh
PKG_VERSION="3.2.0"
PKG_UNSIGNED="output/ProxyBridge-v${PKG_VERSION}-Universal-Installer.pkg"
PKG_SIGNED="output/ProxyBridge-v${PKG_VERSION}-Universal-Installer-signed.pkg"
# Sign pkg with explicit keychain - no prompting
echo "Signing installer..."
KEYCHAIN_PATH=$(security list-keychains -d user | grep build | tr -d ' "')
echo "Using keychain: $KEYCHAIN_PATH"
security unlock-keychain -p "${{ secrets.MACOS_KEYCHAIN_PASSWORD }}" "$KEYCHAIN_PATH"
productsign \
--sign "${{ secrets.MACOS_SIGNING_IDENTITY }}" \
--keychain "$KEYCHAIN_PATH" \
"$PKG_UNSIGNED" "$PKG_SIGNED"
mv "$PKG_SIGNED" "$PKG_UNSIGNED"
# Notarize pkg
echo "Notarizing installer..."
PKG_SUBMIT_OUTPUT=$(xcrun notarytool submit "$PKG_UNSIGNED" \
--apple-id "${{ secrets.APPLE_ID }}" \
--password "${{ secrets.APPLE_APP_PASSWORD }}" \
--team-id "${{ secrets.APPLE_TEAM_ID }}" \
--wait 2>&1)
echo "$PKG_SUBMIT_OUTPUT"
PKG_SUBMISSION_ID=$(echo "$PKG_SUBMIT_OUTPUT" | grep "^ id:" | head -1 | awk '{print $2}')
if [ -n "$PKG_SUBMISSION_ID" ]; then
echo "--- PKG Notarization Log ---"
xcrun notarytool log "$PKG_SUBMISSION_ID" \
--apple-id "${{ secrets.APPLE_ID }}" \
--password "${{ secrets.APPLE_APP_PASSWORD }}" \
--team-id "${{ secrets.APPLE_TEAM_ID }}" 2>&1 || true
fi
if ! echo "$PKG_SUBMIT_OUTPUT" | grep -q "status: Accepted"; then
echo "PKG notarization failed!"
exit 1
fi
xcrun stapler staple "$PKG_UNSIGNED"
echo "PKG signed, notarized and stapled successfully"
- name: Upload PKG Artifact
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: ProxyBridge-macOS-Installer
path: MacOS/ProxyBridge/output/ProxyBridge-*.pkg
retention-days: 30
- name: Cleanup
if: always()
run: |
# Delete temporary keychain
security delete-keychain build.keychain || true
# Remove provisioning profiles
rm -f ~/Library/MobileDevice/Provisioning\ Profiles/*.provisionprofile || true
# Remove temp cert and profile files
rm -f /tmp/certificate.p12 /tmp/installer.p12 /tmp/app.provisionprofile /tmp/ext.provisionprofile /tmp/ProxyBridge.zip || true
# Remove .env with sensitive data
rm -f MacOS/ProxyBridge/.env || true
# Remove xcconfig files with sensitive data
rm -f MacOS/ProxyBridge/Signing-Config-app.xcconfig || true
rm -f MacOS/ProxyBridge/Signing-Config-ext.xcconfig || true