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
202 changes: 202 additions & 0 deletions .github/workflows/input-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
name: Input validation gesture suite

# Fast-running iOS suite that asserts physical taps / drags / long-presses
# reach Component listeners end-to-end. Built to catch regressions in the
# input chain (the class of bug PR #5003 fixed -- a window-level
# UITapGestureRecognizer eating every tap was invisible to the existing
# screenshot-only tests because none of them actually depended on a touch
# event firing).
#
# Only iOS for now. The JavaScript port wires its pointer listeners from
# inside a Web Worker via a host-bridge proxy; synthetic events from the
# test driver don't traverse that proxy the way real OS events would, so
# end-to-end input validation on JS needs port-side work first. See
# scripts/input-validation-app/README.adoc for the "not yet covered" list.

on:
pull_request:
paths:
- '.github/workflows/input-validation.yml'
- 'scripts/input-validation-app/**'
- 'scripts/build-ios-app.sh'
- 'CodenameOne/src/com/codename1/ui/Component.java'
- 'CodenameOne/src/com/codename1/ui/Form.java'
- 'CodenameOne/src/com/codename1/ui/Button.java'
- 'Ports/iOSPort/nativeSources/CN1TapGestureRecognizer.m'
- 'Ports/iOSPort/nativeSources/CodenameOne_GLViewController.m'
push:
branches: [ master ]
paths:
- '.github/workflows/input-validation.yml'
- 'scripts/input-validation-app/**'
- 'scripts/build-ios-app.sh'
workflow_dispatch: {}

jobs:
build-port:
# Reused by `ios` so the iOS port .jar / native sources are available in
# the cache the build-ios-app step relies on. Same reusable workflow that
# scripts-ios.yml depends on -- piggybacking on its cache key.
uses: ./.github/workflows/_build-ios-port.yml

ios:
needs: build-port
permissions:
contents: read
runs-on: macos-15
timeout-minutes: 35
concurrency:
group: mac-ci-${{ github.workflow }}-ios-${{ github.ref_name }}
cancel-in-progress: true
env:
GITHUB_TOKEN: ${{ secrets.CN1SS_GH_TOKEN }}
GH_TOKEN: ${{ secrets.CN1SS_GH_TOKEN }}
CN1_APP_DIR: scripts/input-validation-app
steps:
- uses: actions/checkout@v4

- name: Cache CocoaPods and user gems
uses: actions/cache@v4
with:
path: |
~/.gem
~/Library/Caches/CocoaPods
~/.cocoapods/repos
key: ${{ runner.os }}-pods-v1-${{ hashFiles('scripts/setup-workspace.sh') }}
restore-keys: |
${{ runner.os }}-pods-v1-

- name: Ensure CocoaPods tooling
run: |
mkdir -p ~/.codenameone
cp maven/UpdateCodenameOne.jar ~/.codenameone/
set -euo pipefail
GEM_USER_DIR="$(ruby -e 'print Gem.user_dir')"
export PATH="$GEM_USER_DIR/bin:$PATH"
if ! command -v pod >/dev/null 2>&1; then
gem install cocoapods xcodeproj --no-document --user-install
fi
pod --version

- name: Compute setup-workspace hash
id: setup_hash
run: echo "hash=$(shasum -a 256 scripts/setup-workspace.sh | awk '{print $1}')" >> "$GITHUB_OUTPUT"

- name: Compute CN1 source hash
id: src_hash
run: |
set -euo pipefail
SRC_HASH=$(find CodenameOne/src Ports/iOSPort vm/JavaAPI vm/ByteCodeTranslator Themes native-themes \
-type f \( -name '*.java' -o -name '*.m' -o -name '*.h' -o -name '*.xml' -o -name '*.properties' -o -name '*.css' \) 2>/dev/null \
| sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}')
POM_HASH=$(find . -name 'pom.xml' -not -path './scripts/*' 2>/dev/null \
| sort | xargs shasum -a 256 | shasum -a 256 | awk '{print $1}')
SCRIPT_HASH=$(shasum -a 256 \
scripts/setup-workspace.sh \
scripts/build-ios-port.sh \
scripts/build-native-themes.sh \
.github/workflows/_build-ios-port.yml \
| shasum -a 256 | awk '{print $1}')
echo "hash=${SRC_HASH:0:16}-${POM_HASH:0:16}-${SCRIPT_HASH:0:16}" >> "$GITHUB_OUTPUT"

- name: Set TMPDIR
run: echo "TMPDIR=${{ runner.temp }}" >> $GITHUB_ENV

- name: Cache codenameone-tools
uses: actions/cache@v4
with:
path: ${{ runner.temp }}/codenameone-tools
key: ${{ runner.os }}-cn1-tools-${{ steps.setup_hash.outputs.hash }}
restore-keys: |
${{ runner.os }}-cn1-tools-

- name: Cache Maven repository
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-m2-

- name: Restore cn1-binaries cache
uses: actions/cache@v4
with:
path: ../cn1-binaries
key: cn1-binaries-${{ runner.os }}-${{ steps.setup_hash.outputs.hash }}
restore-keys: |
cn1-binaries-${{ runner.os }}-

- name: Restore built CN1 + iOS port artifacts
uses: actions/cache/restore@v4
with:
path: |
~/.m2/repository/com/codenameone
Themes
Ports/iOSPort/nativeSources
key: cn1-built-${{ runner.os }}-${{ steps.src_hash.outputs.hash }}
fail-on-cache-miss: true

- name: Install XcodeGen
run: brew install xcodegen

- name: Build CN1 input-validation iOS Xcode project
id: build-ios-app
run: ./scripts/build-ios-app.sh -q -DskipTests
timeout-minutes: 25

- name: Build .app bundle for simulator
id: build-app-bundle
run: |
set -euo pipefail
WORKSPACE='${{ steps.build-ios-app.outputs.workspace }}'
SCHEME='${{ steps.build-ios-app.outputs.scheme }}'
DERIVED_DATA="${{ runner.temp }}/cn1iv-dd"
rm -rf "$DERIVED_DATA"
# Force ARCHS to match the host. IOSSimd.m uses ARM NEON intrinsics
# under #if defined(__aarch64__) -- without ONLY_ACTIVE_ARCH=YES the
# generic simulator destination triggers a universal build whose
# x86_64 slice fails to compile. Matches what run-ios-ui-tests.sh
# does for the hellocodenameone build.
HOST_ARCH="$(uname -m)"
case "$HOST_ARCH" in
arm64|x86_64) BUILD_ARCH="$HOST_ARCH" ;;
*) BUILD_ARCH=arm64 ;;
esac
XCB_CONTAINER_FLAG="-workspace"
if [[ "$WORKSPACE" != *.xcworkspace ]]; then
XCB_CONTAINER_FLAG="-project"
fi
xcodebuild $XCB_CONTAINER_FLAG "$WORKSPACE" -scheme "$SCHEME" \
-sdk iphonesimulator \
-configuration Debug \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath "$DERIVED_DATA" \
ARCHS=$BUILD_ARCH ONLY_ACTIVE_ARCH=YES \
EXCLUDED_ARCHS="armv7 armv7s" \
CODE_SIGNING_ALLOWED=NO build
APP_BUNDLE="$(find "$DERIVED_DATA/Build/Products" -maxdepth 3 -type d -name "${SCHEME}.app" | head -n 1)"
if [ -z "$APP_BUNDLE" ]; then
echo "Failed to locate .app bundle under $DERIVED_DATA" >&2
find "$DERIVED_DATA/Build/Products" -maxdepth 4 -type d -print >&2 || true
exit 1
fi
echo "app_bundle=$APP_BUNDLE" >> "$GITHUB_OUTPUT"
timeout-minutes: 15

- name: Drive gestures via XCUITest
env:
ARTIFACTS_DIR: ${{ github.workspace }}/artifacts/input-validation-ios
run: |
mkdir -p "$ARTIFACTS_DIR"
./scripts/input-validation-app/drivers/run-ios.sh \
'${{ steps.build-app-bundle.outputs.app_bundle }}'
timeout-minutes: 15

- name: Upload iOS artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: input-validation-ios
path: artifacts/input-validation-ios
if-no-files-found: warn
retention-days: 14
41 changes: 25 additions & 16 deletions scripts/build-ios-app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,21 @@ if [ -n "${IOS_DEPENDENCY_ARGS:-}" ]; then
bia_log "Applying extra iOS build args: ${IOS_DEPENDENCY_ARGS}"
fi

APP_DIR="scripts/hellocodenameone"
APP_DIR="${CN1_APP_DIR:-scripts/hellocodenameone}"

# Derive the iOS project / scheme name from the app's own CN1 settings so
# this script can build any CN1 app, not just hellocodenameone.
CN1_SETTINGS_FILE="$REPO_ROOT/$APP_DIR/common/codenameone_settings.properties"
if [ -f "$CN1_SETTINGS_FILE" ]; then
MAIN_NAME_FROM_SETTINGS="$(awk -F= '/^codename1.mainName=/{print $2; exit}' "$CN1_SETTINGS_FILE" | tr -d '\r')"
fi
APP_MAIN_NAME="${CN1_APP_MAIN_NAME:-${MAIN_NAME_FROM_SETTINGS:-HelloCodenameOne}}"
bia_log "Using APP_DIR=$APP_DIR APP_MAIN_NAME=$APP_MAIN_NAME"

xcodebuild -version

bia_log "Building iOS Xcode project using Codename One port"
cd $APP_DIR
cd "$REPO_ROOT/$APP_DIR"
VM_START=$(date +%s)

ARTIFACTS_DIR="${ARTIFACTS_DIR:-$REPO_ROOT/artifacts}"
Expand Down Expand Up @@ -175,11 +184,11 @@ stage_bytecode_translator_sources() {
bia_log "Created archive $zip_file"
}

bia_log "Running HelloCodenameOne Maven build with JAVA_HOME=$JAVA17_HOME"
bia_log "Running $APP_MAIN_NAME Maven build with JAVA_HOME=$JAVA17_HOME"
(
export JAVA_HOME="$JAVA17_HOME"
export PATH="$JAVA_HOME/bin:$MAVEN_HOME/bin:$BASE_PATH"
MVN_IOS_LOG="$ARTIFACTS_DIR/hellocn1-ios-build.log"
MVN_IOS_LOG="$ARTIFACTS_DIR/cn1-ios-build.log"
MVN_CMD=(
./mvnw package
-DskipTests
Expand Down Expand Up @@ -211,7 +220,7 @@ bia_log "Running HelloCodenameOne Maven build with JAVA_HOME=$JAVA17_HOME"
)
VM_END=$(date +%s)
VM_TIME=$((VM_END - VM_START))
cd ../..
cd "$REPO_ROOT"

echo "$VM_TIME" > "$ARTIFACTS_DIR/vm_time.txt"
bia_log "VM translation time: ${VM_TIME}s (saved to $ARTIFACTS_DIR/vm_time.txt)"
Expand Down Expand Up @@ -269,22 +278,22 @@ else
bia_log "Podfile not found in generated project; skipping pod install"
fi

WORKSPACE_XML='<?xml version="1.0" encoding="UTF-8"?>
WORKSPACE_XML="<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<Workspace
version = "1.0">
version = \"1.0\">
<FileRef
location = "group:HelloCodenameOne.xcodeproj">
location = \"group:${APP_MAIN_NAME}.xcodeproj\">
</FileRef>
</Workspace>'
if [ ! -d "$PROJECT_DIR/HelloCodenameOne.xcworkspace" ] && [ -d "$PROJECT_DIR/HelloCodenameOne.xcodeproj" ]; then
</Workspace>"
if [ ! -d "$PROJECT_DIR/${APP_MAIN_NAME}.xcworkspace" ] && [ -d "$PROJECT_DIR/${APP_MAIN_NAME}.xcodeproj" ]; then
bia_log "Creating fallback xcworkspace for generated Xcode project"
mkdir -p "$PROJECT_DIR/HelloCodenameOne.xcworkspace"
printf '%s\n' "$WORKSPACE_XML" > "$PROJECT_DIR/HelloCodenameOne.xcworkspace/contents.xcworkspacedata"
mkdir -p "$PROJECT_DIR/${APP_MAIN_NAME}.xcworkspace"
printf '%s\n' "$WORKSPACE_XML" > "$PROJECT_DIR/${APP_MAIN_NAME}.xcworkspace/contents.xcworkspacedata"
fi

if [ -d "$PROJECT_DIR/HelloCodenameOne.xcodeproj" ]; then
if [ -d "$PROJECT_DIR/${APP_MAIN_NAME}.xcodeproj" ]; then
bia_log "Ensuring shared Xcode scheme exists"
"$REPO_ROOT/scripts/ios/create-shared-scheme.py" "$PROJECT_DIR" HelloCodenameOne
"$REPO_ROOT/scripts/ios/create-shared-scheme.py" "$PROJECT_DIR" "$APP_MAIN_NAME"
fi

# Locate workspace or project for the next step
Expand Down Expand Up @@ -315,11 +324,11 @@ bia_log "Found Xcode entrypoint: $WORKSPACE"
if [ -n "${GITHUB_OUTPUT:-}" ]; then
{
echo "workspace=$WORKSPACE"
echo "scheme=HelloCodenameOne"
echo "scheme=$APP_MAIN_NAME"
} >> "$GITHUB_OUTPUT"
fi

bia_log "Emitted outputs -> workspace=$WORKSPACE, scheme=HelloCodenameOne"
bia_log "Emitted outputs -> workspace=$WORKSPACE, scheme=$APP_MAIN_NAME"

# (Optional) dump xcodebuild -list for debugging
ARTIFACTS_DIR="${ARTIFACTS_DIR:-$REPO_ROOT/artifacts}"
Expand Down
Empty file.
Loading
Loading