Files
Felitendo d77de62c5a chore: move the actions off the Node 20 runtime
GitHub now forces actions/checkout, actions/cache and softprops/action-gh-release
onto Node 24 and warns on every run, because the majors pinned here still declare
Node 20. Forcing works until it stops.

Each moves to the major that made the runtime change and no further:
checkout v5, cache v5, action-gh-release v3. The newer majors after those carry
unrelated changes, a credential file move and an ESM migration among them, and
none of that is what the deprecation is asking for. The inputs used here are the
same in all of them, so nothing else needed touching.

They require a runner of 2.327.1 or newer, which every GitHub-hosted runner is.
The docker actions were never affected.
2026-08-26 16:45:40 +02:00

118 lines
5.6 KiB
YAML

name: iOS Dev Repo
# Builds an unsigned dev IPA and publishes it together with a freshly-generated
# AltStore source (devrepo.json) to a rolling "dev" prerelease.
# https://github.com/FTStuff/FTStore/releases/download/dev/devrepo.json
#
# Monorepo: the Xcode project lives in ios/, so every build step runs there.
# app-repo.json stays at the repo root — its raw.githubusercontent URL is what
# users have subscribed to, so it must not move.
on:
push:
branches: [main]
paths:
- "ios/**"
- ".github/workflows/ios-dev-repo.yml"
workflow_dispatch:
concurrency:
group: dev-repo-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
jobs:
build:
# macOS label required: the bare `self-hosted` label also matches the org's
# Linux runners, which have no xcodebuild and fail the build outright.
runs-on: [self-hosted, macOS]
env:
DEVELOPER_DIR: /Applications/Xcode.app/Contents/Developer # statt sudo xcode-select
steps:
- name: Checkout
uses: actions/checkout@v5
with:
submodules: recursive
fetch-depth: 1
- name: Cache SwiftPM
uses: actions/cache@v5
with:
path: ~/Library/Caches/org.swift.swiftpm
key: spm-${{ runner.os }}-${{ hashFiles('**/Package.resolved') }}
restore-keys: spm-${{ runner.os }}-
- name: Compute dev version
run: |
BASE=$(grep '^FTSTORE_PROJECT_VERSION' ios/FTStore.xcconfig | cut -d= -f2 | tr -d '[:space:]')
echo "VERSION=${BASE}-dev.${{ github.run_number }}" >> "$GITHUB_ENV"
echo "DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_ENV"
- name: Stamp marketing version
# NOT agvtool: it writes CFBundleShortVersionString into Info.plist, but
# the target sets MARKETING_VERSION = $(FTSTORE_PROJECT_VERSION) and
# GENERATE_INFOPLIST_FILE = YES, so Xcode regenerates that key from the
# build setting and the edit is thrown away. The IPA then reports the
# base version while devrepo.json advertises the dev one, and every
# AltStore client sees a permanent "update available". Set the variable
# the build actually reads, and fail loudly if it ever stops matching.
run: |
sed -i '' "s|^FTSTORE_PROJECT_VERSION=.*|FTSTORE_PROJECT_VERSION=${VERSION}|" ios/FTStore.xcconfig
grep -q "^FTSTORE_PROJECT_VERSION=${VERSION}$" ios/FTStore.xcconfig
- name: Stamp build number (best effort)
# Records the source commit in CFBundleVersion. Best effort because
# agvtool trips over GENERATE_INFOPLIST_FILE=YES ("Cannot find …/YES")
# while still doing the write.
continue-on-error: true
working-directory: ios
run: agvtool new-version -all "${{ github.sha }}"
- name: Build (iphoneos, unsigned)
working-directory: ios
run: make iphoneos
- name: Verify the Live Activity extension shipped and can load
# The Dynamic Island lives in an embedded appex, so an IPA that is wrong
# about it installs and runs perfectly — the island just never appears,
# and nothing in the build says why. Every check here is for a way that
# can happen silently:
#
# missing the extension is not in the IPA at all. This is what
# happened when manager/ shared this build's derived data
# (identical project, scheme, target and pbxproj GUIDs)
# and its stale-file sweep went after an extension it has
# no target for.
# wrong id iOS refuses to load an app extension whose bundle id is
# not prefixed by its host app's, and says nothing. The
# two ids are built from separate settings in the pbxproj,
# so one can drift from the other — and a disambiguator
# applied to the app but not the extension does exactly
# that.
# wrong point a widget extension must declare the widgetkit extension
# point. Without it the appex is dead weight.
#
# Presence alone was the old check. It passed on all three of these.
run: ios/scripts/verify-live-activity.sh ios/packages/FTStore.ipa
- name: Generate devrepo.json
run: |
IPA=ios/packages/FTStore.ipa
SIZE=$(stat -f%z "$IPA")
URL="https://github.com/${{ github.repository }}/releases/download/dev/FTStore.ipa"
jq \
--arg v "$VERSION" --arg d "$DATE" --argjson s "$SIZE" --arg u "$URL" '
.name = "FTStore (Dev)" |
.identifier = "app.ftstore.devrepo" |
.apps[0].name = "FTStore (Dev)" |
.apps[0].subtitle = "Latest commit build — for testing" |
.apps[0].version = $v |
.apps[0].versionDate = $d |
.apps[0].size = $s |
.apps[0].downloadURL = $u |
.apps[0].versions = [ { "version": $v, "date": $d, "size": $s, "downloadURL": $u } ] |
.news = []
' app-repo.json > devrepo.json
echo "Generated devrepo.json for $VERSION (${SIZE} bytes)"
- name: Publish dev prerelease
uses: softprops/action-gh-release@v3
with:
tag_name: dev
name: Dev build
prerelease: true
make_latest: false
body: "Rolling development build of the latest `main` commit (${{ github.sha }}). Unsigned — FTStore (formerly Feather) signs it on-device at install."
files: |
ios/packages/FTStore.ipa
devrepo.json