Skip to content

Externalize data

Externalize data #40

Workflow file for this run

name: Build with PyInstaller
on:
workflow_dispatch:
inputs:
artifact_name:
description: 'Artifact name'
required: false
push:
branches: [package]
jobs:
build:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
# runs-on: [self-hosted, macOS, ARM64]
strategy:
matrix:
# os: [ubuntu-latest, macos-latest-xlarge, windows-latest]
os: [macos-latest-xlarge]
python-version: [3.11]
node-version: [20]
steps:
- uses: actions/checkout@v4
- name: Install the Apple certificate and provisioning profile
if: runner.os == 'macOS'
env:
APPLE_BUILD_CERTIFICATE_BASE64: ${{ secrets.APPLE_BUILD_CERTIFICATE_BASE64 }}
APPLE_BUILD_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_BUILD_CERTIFICATE_PASSWORD }}
APPLE_PROVISIONING_PROFILE_BASE64: ${{ secrets.APPLE_PROVISIONING_PROFILE_BASE64 }}
APPLE_MACOS_KEYCHAIN_PASSWORD: ${{ secrets.APPLE_MACOS_KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/apple_certificate.p12
PROVISIONING_PROFILE_PATH=$RUNNER_TEMP/apple_provisioning_profile.provisionprofile
KEYCHAIN_PATH=$RUNNER_TEMP/github-actions.keychain-db
KEYCHAIN_NAME=github-actions
# import certificate and provisioning profile from secrets
echo -n "$APPLE_BUILD_CERTIFICATE_BASE64" | base64 --decode > $CERTIFICATE_PATH
echo -n "$APPLE_PROVISIONING_PROFILE_BASE64" | base64 --decode > $PROVISIONING_PROFILE_PATH
# create temporary keychain
security create-keychain -p "$APPLE_MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$APPLE_MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security default-keychain -s $KEYCHAIN_PATH
# import certificate to keychain
security import $CERTIFICATE_PATH -P "$APPLE_BUILD_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security set-key-partition-list -S apple-tool:,apple: -k "$APPLE_MACOS_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PROVISIONING_PROFILE_PATH ~/Library/MobileDevice/Provisioning\ Profiles
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: poetry
cache-dependency-path: poetry.lock
- name: Install dependencies with Poetry
run: poetry install --no-dev
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
cache-dependency-path: selfie-ui/yarn.lock
- name: Cache Next.js build artifacts
uses: actions/cache@v4
with:
path: |
selfie-ui/.next/cache
key: ${{ runner.os }}-nextjs-${{ hashFiles('selfie-ui/**/yarn.lock') }}-${{ hashFiles('selfie-ui/**/*.js', 'selfie-ui/**/*.jsx', 'selfie-ui/**/*.ts', 'selfie-ui/**/*.tsx') }}
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('selfie-ui/**/yarn.lock') }}-
- name: Install dependencies with Yarn
run: sh scripts/build-ui.sh
- name: Install PyInstaller
run: poetry run pip install pyinstaller
- name: Build with PyInstaller
run: poetry run pyinstaller selfie.spec --noconfirm
shell: bash
- name: Set executable permissions
run: chmod +x dist/selfie/selfie
- name: Build macOS App
if: runner.os == 'macOS'
env:
APPLE_ASC_API_KEY_KEY_BASE64: ${{ secrets.APPLE_ASC_API_KEY_KEY_BASE64 }}
run: |
sh scripts/package-macos-app.sh # TODO: pass in CERT, etc.
# Create a ZIP archive of the app bundle
ditto -c -k --keepParent "${{ github.workspace }}/dist/Selfie.app" "${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip"
echo "Submitting app for notarization..."
API_KEY_PATH=$RUNNER_TEMP/AuthKey_${{secrets.APPLE_ASC_API_KEY_ID}}.p8
echo -n "$APPLE_ASC_API_KEY_KEY_BASE64" | base64 --decode > $API_KEY_PATH
# Submit the ZIP archive for notarization
NOTARIZATION_OUTPUT=$(xcrun notarytool submit "${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip" --issuer ${{ secrets.APPLE_ASC_API_KEY_ISSUER_UUID }} --key-id ${{ secrets.APPLE_ASC_API_KEY_ID }} --key $API_KEY_PATH --wait 2>&1)
# Parse the REQUEST_UUID and notarization status from NOTARIZATION_OUTPUT
REQUEST_UUID=$(echo "${NOTARIZATION_OUTPUT}" | grep 'id:' | awk '{print $NF}')
NOTARIZATION_STATUS=$(echo "${NOTARIZATION_OUTPUT}" | grep 'status:' | tail -n 1 | awk '{print $NF}')
# Check if REQUEST_UUID is empty
if [[ -z "$REQUEST_UUID" ]]; then
echo "Failed to submit app for notarization. Full output:"
echo "${NOTARIZATION_OUTPUT}"
exit 1
else
echo "Notarization submitted; RequestUUID: ${REQUEST_UUID}"
fi
# Handle notarization status
if [[ "$NOTARIZATION_STATUS" == "Invalid" ]]; then
echo "Notarization failed with status: ${NOTARIZATION_STATUS}"
echo "Fetching notarization log for RequestUUID: ${REQUEST_UUID}..."
xcrun notarytool log ${REQUEST_UUID} --key $API_KEY_PATH --key-id ${{ secrets.APPLE_ASC_API_KEY_ID }} --issuer ${{ secrets.APPLE_ASC_API_KEY_ISSUER_UUID }}
exit 1
elif [[ "$NOTARIZATION_STATUS" != "Accepted" ]]; then
echo "Notarization failed with an unexpected status: ${NOTARIZATION_STATUS}"
echo "Full notarization output:"
echo "${NOTARIZATION_OUTPUT}"
exit 1
else
echo "Notarization successful; status: ${NOTARIZATION_STATUS}"
fi
# Staple the notarization ticket to the app bundle
xcrun stapler staple "${{ github.workspace }}/dist/Selfie.app"
# Create the final ZIP archive of the notarized app bundle
ditto -c -k --keepParent "${{ github.workspace }}/dist/Selfie.app" "${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip"
- name: Build Non-macOS App
if: runner.os != 'macOS'
run: zip -r ${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip dist/selfie
shell: bash
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}
path: ${{ github.event.inputs.artifact_name || format('{0}-build', matrix.os) }}.zip
overwrite: true
- name: Clean up keychain and provisioning profile
if: runner.os == 'macOS'
run: |
security delete-keychain $RUNNER_TEMP/github-actions.keychain-db
rm ~/Library/MobileDevice/Provisioning\ Profiles/apple_provisioning_profile.provisionprofile