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
169 changes: 169 additions & 0 deletions .github/workflows/build-and-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
name: Build & Release iOS and macOS Extensions

on:
push:
branches:
- main
paths:
- '**.swift'
- 'ios/**'
- 'mos/**'
- '.github/workflows/build-and-release.yml'
workflow_dispatch:
inputs:
draft:
description: 'Create as draft (for testing)'
required: true
default: 'true'
type: choice
options:
- 'true'
- 'false'

jobs:
check-version:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
version: ${{ steps.extract.outputs.version }}
tag_exists: ${{ steps.check_tag.outputs.exists }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true

- name: Extract version from Xcode project
id: extract
run: |
VERSION=$(grep -m1 'MARKETING_VERSION = ' ios/Flean.xcodeproj/project.pbxproj | awk -F ' = ' '{ gsub(/;/,"",$2); print $2; exit }')
echo "version=v$VERSION" >> $GITHUB_OUTPUT
echo "Detected version: v$VERSION"

- name: Check if tag exists
id: check_tag
run: |
if git ls-remote --tags --exit-code origin "refs/tags/${{ steps.extract.outputs.version }}" >/dev/null 2>&1; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "Tag already exists!"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "Tag does not exist - ready to build"
fi

build-and-release:
needs: check-version
if: needs.check-version.outputs.tag_exists == 'false'
runs-on: macos-latest
permissions:
contents: write

steps:
- uses: actions/checkout@v4

# iOS Build
- name: Build iOS App
run: |
cd ios
mkdir -p build

xcodebuild build \
-project Flean.xcodeproj \
-target Flean \
-configuration Release \
-destination 'generic/platform=iOS' \
-skipPackagePluginValidation \
SYMROOT=build \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGN_ENTITLEMENTS=""

# Package the .app as a proper IPA (Payload/Flean.app zipped)
APP_PATH=$(find build -name "Flean.app" -type d | head -1)
if [ -z "$APP_PATH" ]; then
echo "❌ Flean.app not found"
exit 1
fi
mkdir -p build/ipa/Payload
cp -r "$APP_PATH" build/ipa/Payload/
( cd build/ipa && zip -r ../Flean.ipa Payload )
echo "✅ iOS build succeeded"

# macOS Build
- name: Build macOS App
run: |
cd mos
mkdir -p build

xcodebuild build \
-project Flean.xcodeproj \
-target Flean \
-configuration Release \
-skipPackagePluginValidation \
SYMROOT=build \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGN_ENTITLEMENTS=""

# Find and zip the .app into a fixed location matching the upload step
APP_PATH=$(find build -name "Flean.app" -type d | head -1)
if [ -z "$APP_PATH" ]; then
echo "❌ Flean.app not found"
exit 1
fi

# Create a zip whose top-level entry is Flean.app
OUT_ZIP="$(pwd)/build/Flean.app.zip"
APP_DIR="$(dirname "$APP_PATH")"
APP_NAME="$(basename "$APP_PATH")"
( cd "$APP_DIR" && zip -r "$OUT_ZIP" "$APP_NAME" )
echo "✅ macOS build succeeded"

# Create tag
- name: Create Git Tag
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
VERSION="${{ needs.check-version.outputs.version }}"
# Create local tag (no-op if already exists locally from a shallow clone)
git tag "$VERSION" 2>/dev/null || echo "Local tag $VERSION already exists, proceeding with push"
# Push to remote; fail clearly if the tag was created by a concurrent run
if ! git push origin "$VERSION"; then
echo "::error::Tag $VERSION already exists on remote. A release for this version may already exist."
exit 1
fi

# Create Release
- name: Create Release
uses: actions/create-release@v1
id: create_release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ needs.check-version.outputs.version }}
release_name: "Flean ${{ needs.check-version.outputs.version }}"
draft: ${{ github.event.inputs.draft == 'true' }}
prerelease: false

# Upload iOS App
- name: Upload iOS App
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./ios/build/Flean.ipa
asset_name: Flean.ipa
asset_content_type: application/octet-stream

# Upload macOS App
- name: Upload macOS App
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./mos/build/Flean.app.zip
asset_name: Flean.app.zip
asset_content_type: application/zip
122 changes: 122 additions & 0 deletions .github/workflows/prerelease.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Create Prerelease on PR Ready

on:
pull_request:
branches:
- main
types:
- ready_for_review
paths:
- '.github/workflows/**'
- '**.swift'
- 'ios/**'
- 'mos/**'

jobs:
create-prerelease:
runs-on: macos-latest
permissions:
contents: write

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Extract version from Xcode project
id: extract
run: |
VERSION=$(grep -m1 'MARKETING_VERSION = ' ios/Flean.xcodeproj/project.pbxproj | awk -F ' = ' '{ gsub(/;/,"",$2); print $2; exit }')
echo "version=v$VERSION" >> $GITHUB_OUTPUT
echo "Detected version: v$VERSION"

- name: Build iOS
run: |
cd ios
mkdir -p build

xcodebuild build \
-project Flean.xcodeproj \
-target Flean \
-configuration Release \
-destination 'generic/platform=iOS' \
-skipPackagePluginValidation \
SYMROOT=build \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGN_ENTITLEMENTS=""

# Package the .app as a proper IPA (Payload/Flean.app zipped)
APP_PATH=$(find build -name "Flean.app" -type d | head -1)
if [ -z "$APP_PATH" ]; then
echo "❌ Flean.app not found"
exit 1
fi
mkdir -p build/ipa/Payload
cp -r "$APP_PATH" build/ipa/Payload/
( cd build/ipa && zip -r ../Flean.ipa Payload )
echo "✅ iOS build succeeded"

- name: Build macOS
run: |
cd mos
mkdir -p build

xcodebuild build \
-project Flean.xcodeproj \
-target Flean \
-configuration Release \
-skipPackagePluginValidation \
SYMROOT=build \
CODE_SIGN_IDENTITY="" \
CODE_SIGNING_REQUIRED=NO \
CODE_SIGN_ENTITLEMENTS=""

# Find and zip the .app
APP_PATH=$(find build -name "Flean.app" -type d | head -1)
if [ -z "$APP_PATH" ]; then
echo "❌ Flean.app not found"
exit 1
fi
OUT_ZIP="$(pwd)/build/Flean.app.zip"
APP_DIR="$(dirname "$APP_PATH")"
APP_NAME="$(basename "$APP_PATH")"
( cd "$APP_DIR" && zip -r "$OUT_ZIP" "$APP_NAME" )
echo "✅ macOS build succeeded"

- name: Create Prerelease
uses: actions/create-release@v1
id: create_prerelease
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.extract.outputs.version }}-prerelease-${{ github.run_number }}
release_name: "Flean ${{ steps.extract.outputs.version }} - Prerelease (PR #${{ github.event.pull_request.number }})"
Comment thread
kiyarose marked this conversation as resolved.
body: |
🧪 **Prerelease Build** from PR #${{ github.event.pull_request.number }}

**Branch:** ${{ github.event.pull_request.head.ref }}
**Author:** @${{ github.event.pull_request.user.login }}

This is a prerelease. Testing and feedback welcome!
draft: false
prerelease: true

- name: Upload iOS App
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_prerelease.outputs.upload_url }}
asset_path: ./ios/build/Flean.ipa
asset_name: Flean.ipa
asset_content_type: application/octet-stream

- name: Upload macOS App
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_prerelease.outputs.upload_url }}
asset_path: ./mos/build/Flean.app.zip
asset_name: Flean.app.zip
asset_content_type: application/zip
22 changes: 8 additions & 14 deletions ios/Flean.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -576,20 +576,17 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Flean/Flean.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = PWL627GZ4Y;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = Flean;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSMainStoryboardFile = Main;
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 2.1.3;
OTHER_LDFLAGS = (
"-framework",
Expand All @@ -599,7 +596,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = slf.Flean;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
Expand All @@ -615,20 +612,17 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Flean/Flean.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2;
DEVELOPMENT_TEAM = PWL627GZ4Y;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_CFBundleDisplayName = Flean;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSMainStoryboardFile = Main;
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@executable_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
MARKETING_VERSION = 2.1.3;
OTHER_LDFLAGS = (
"-framework",
Expand All @@ -638,7 +632,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = slf.Flean;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
13 changes: 4 additions & 9 deletions ios/Flean/iOS/FleanApp.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
// iOS-only app entry. Guard so the file can live in the repo without
// conflicting with the macOS `@main` app in `Flean/AppDelegate.swift`.
#if os(iOS)
import SwiftUI
import WebKit

@main
struct FleanApp: App {
var body: some Scene {
WindowGroup {
WebViewContainer()
}
var body: some Scene {
WindowGroup {
WebViewContainer()
}
}
}

#endif
Loading