diff --git a/.ci/container/Dockerfile b/.ci/container/Dockerfile new file mode 100644 index 0000000000..dafc71e572 --- /dev/null +++ b/.ci/container/Dockerfile @@ -0,0 +1,124 @@ +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive + +# Install common dependencies +# libncurses6 is needed for some android tools on newer ubuntu? or libncurses5? +# Ubuntu 24.04 has libncurses6 by default. libncurses5 might need a legacy package or symlink. +# We will try installing libncurses5 but it might not be available. We'll install libncurses6 and maybe symlink if needed. +# Actually, the android sdk manager usually works with 6. +# We include basic build tools and libraries. +RUN apt-get update && apt-get install -y \ + curl \ + wget \ + git \ + unzip \ + zip \ + python3 \ + python3-pip \ + sudo \ + xvfb \ + ant \ + maven \ + libncurses6 \ + libstdc++6 \ + libxrender1 \ + libxtst6 \ + libxi6 \ + clang \ + gnupg \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# Install Azul Zulu Repository +RUN curl -s https://repos.azul.com/azul-repo.key | gpg --dearmor -o /usr/share/keyrings/azul.gpg \ + && echo "deb [signed-by=/usr/share/keyrings/azul.gpg] https://repos.azul.com/zulu/deb stable main" | tee /etc/apt/sources.list.d/zulu.list \ + && apt-get update + +# Install Java versions + +# Zulu 8 with FX (Manual download to ensure FX presence and version stability) +# Using a known working URL for ZuluFX 8 Linux x64 +RUN mkdir -p /usr/lib/jvm && \ + wget -q https://cdn.azul.com/zulu/bin/zulu8.82.0.21-ca-fx-jdk8.0.432-linux_x64.tar.gz -O /tmp/zulu8.tar.gz && \ + tar -xf /tmp/zulu8.tar.gz -C /usr/lib/jvm && \ + mv /usr/lib/jvm/zulu8.82.0.21-ca-fx-jdk8.0.432-linux_x64 /usr/lib/jvm/zulu8-fx && \ + rm /tmp/zulu8.tar.gz + +# Install other JDKs via apt +RUN apt-get install -y \ + zulu11-jdk \ + zulu17-jdk \ + zulu21-jdk + +# Note: zulu25-jdk might be available. If not, this step might fail. +# If it fails, we will have to adjust. But the user implies availability. +RUN apt-get install -y zulu25-jdk || echo "zulu25-jdk install failed, proceeding without it" + +# Android SDK +ENV ANDROID_HOME=/opt/android/sdk +RUN mkdir -p ${ANDROID_HOME}/cmdline-tools && \ + wget -q https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip -O /tmp/cmdline-tools.zip && \ + unzip /tmp/cmdline-tools.zip -d ${ANDROID_HOME}/cmdline-tools && \ + mv ${ANDROID_HOME}/cmdline-tools/cmdline-tools ${ANDROID_HOME}/cmdline-tools/latest && \ + rm /tmp/cmdline-tools.zip + +ENV PATH=${PATH}:${ANDROID_HOME}/cmdline-tools/latest/bin:${ANDROID_HOME}/platform-tools + +# Accept licenses and install packages +RUN yes | sdkmanager --licenses && \ + sdkmanager "platform-tools" "platforms;android-31" "platforms;android-33" "platforms;android-34" "build-tools;31.0.0" "build-tools;33.0.1" "build-tools;34.0.0" "ndk;25.2.9519653" + +# cn1-binaries +ENV CN1_BINARIES=/opt/cn1-binaries +RUN git clone --depth=1 https://github.com/codenameone/cn1-binaries.git ${CN1_BINARIES} + +# Environment Variables +ENV JAVA_HOME=/usr/lib/jvm/zulu8-fx +ENV JAVA8_HOME=/usr/lib/jvm/zulu8-fx +ENV JDK8_HOME=/usr/lib/jvm/zulu8-fx + +# Paths for other JDKs (Assuming standard Azul apt paths, but checking via wildcard expansion in shell if we could, +# but here we hardcode likely paths based on Azul naming convention on Ubuntu) +# Azul usually installs to /usr/lib/jvm/zulu--amd64 or similar. +# Let's inspect typical paths: /usr/lib/jvm/zulu-11-amd64 +# Actually, checking online, it seems to be /usr/lib/jvm/zulu11-ca-amd64 for CA builds, or zulu-11-amd64. +# We will use symlinks or generic paths if possible. +# But to be safe, we can look for them. +# Since we can't run dynamic shell in ENV, we will try the most common one. +# If these paths are wrong, the build might fail later when finding java. +# We will verify them in a RUN step or create symlinks. + +RUN for v in 11 17 21 25; do \ + dir=$(ls -d /usr/lib/jvm/zulu*${v}* 2>/dev/null | head -n 1); \ + if [ -n "$dir" ]; then \ + echo "Linking $dir to /usr/lib/jvm/java-${v}-zulu"; \ + ln -s "$dir" "/usr/lib/jvm/java-${v}-zulu"; \ + else \ + echo "Java ${v} not found"; \ + fi \ + done + +ENV JAVA11_HOME=/usr/lib/jvm/java-11-zulu +ENV JDK11_HOME=/usr/lib/jvm/java-11-zulu +ENV JAVA17_HOME=/usr/lib/jvm/java-17-zulu +ENV JDK17_HOME=/usr/lib/jvm/java-17-zulu +ENV JAVA21_HOME=/usr/lib/jvm/java-21-zulu +ENV JDK21_HOME=/usr/lib/jvm/java-21-zulu +ENV JAVA25_HOME=/usr/lib/jvm/java-25-zulu +ENV JDK25_HOME=/usr/lib/jvm/java-25-zulu + +# Set default java to 8 +RUN update-alternatives --install /usr/bin/java java /usr/lib/jvm/zulu8-fx/bin/java 100 && \ + update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/zulu8-fx/bin/javac 100 + +# Set locale to UTF-8 +RUN apt-get update && apt-get install -y locales && \ + locale-gen en_US.UTF-8 && \ + update-locale LANG=en_US.UTF-8 + +ENV LANG=en_US.UTF-8 \ + LANGUAGE=en_US:en \ + LC_ALL=en_US.UTF-8 + +CMD ["/bin/bash"] diff --git a/.github/workflows/ant.yml b/.github/workflows/ant.yml index 9644107db0..6d4de384df 100644 --- a/.github/workflows/ant.yml +++ b/.github/workflows/ant.yml @@ -7,20 +7,28 @@ on: paths-ignore: - 'CodenameOneDesigner/**' +permissions: + contents: read + packages: read + jobs: build-linux-jdk8: runs-on: ubuntu-latest + container: + image: ghcr.io/codenameone/codenameone/ci-container:latest + options: --user root + defaults: + run: + shell: bash steps: - uses: actions/checkout@v1 - - name: Set up JDK 8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - java-package: jdk - - name: Install dependencies - run: sudo apt-get update && sudo apt-get install xvfb + # JDK 8 is default in container, or we set it explicitly + - name: Configure Java + run: echo "JAVA_HOME=$JAVA8_HOME" >> $GITHUB_ENV + + # dependencies (xvfb) are in container - name: Build with Maven run: | cd maven diff --git a/.github/workflows/build-container.yml b/.github/workflows/build-container.yml new file mode 100644 index 0000000000..b0a1292928 --- /dev/null +++ b/.github/workflows/build-container.yml @@ -0,0 +1,40 @@ +name: Build Container + +on: + push: + branches: + - master + paths: + - '.ci/container/**' + pull_request: + paths: + - '.ci/container/**' + workflow_dispatch: + +permissions: + packages: write + contents: read + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Lowercase repository name + run: | + echo "REPO=${GITHUB_REPOSITORY,,}" >> ${GITHUB_ENV} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: .ci/container + push: ${{ github.event_name != 'pull_request' }} + tags: ghcr.io/${{ env.REPO }}/ci-container:latest,ghcr.io/codenameone/codenameone/ci-container:latest diff --git a/.github/workflows/parparvm-tests.yml b/.github/workflows/parparvm-tests.yml index 31e30ee3d8..d665ce305d 100644 --- a/.github/workflows/parparvm-tests.yml +++ b/.github/workflows/parparvm-tests.yml @@ -15,66 +15,37 @@ on: - '!vm/**/readme.md' - '!vm/**/docs/**' +permissions: + contents: read + packages: read + jobs: vm-tests: runs-on: ubuntu-latest + container: + image: ghcr.io/codenameone/codenameone/ci-container:latest + options: --user root + defaults: + run: + shell: bash steps: - name: Check out repository uses: actions/checkout@v4 - - name: Install native build tools - run: | - sudo apt-get update - sudo apt-get install -y clang - - # Install JDKs and export their paths - - name: Set up JDK 8 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '8' - - name: Save JDK 8 Path - run: echo "JDK_8_HOME=$JAVA_HOME" >> $GITHUB_ENV - - - name: Set up JDK 11 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '11' - - name: Save JDK 11 Path - run: echo "JDK_11_HOME=$JAVA_HOME" >> $GITHUB_ENV - - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '17' - - name: Save JDK 17 Path - run: echo "JDK_17_HOME=$JAVA_HOME" >> $GITHUB_ENV + # Native tools (clang) and JDKs are pre-installed in container. + # Environment variables JDK_8_HOME etc are already set in container or we map them. - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '21' - - name: Save JDK 21 Path - run: echo "JDK_21_HOME=$JAVA_HOME" >> $GITHUB_ENV + # Ensure container env vars are mapped to what tests expect if different. + # The container sets JDK8_HOME, JDK11_HOME, JDK17_HOME, JDK21_HOME, JDK25_HOME. + # The test expects JDK_8_HOME (with underscore). - - name: Set up JDK 25 - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: '25' - - name: Save JDK 25 Path - run: echo "JDK_25_HOME=$JAVA_HOME" >> $GITHUB_ENV - - # Restore JDK 8 as the main runner - - name: Restore JDK 8 - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '8' - cache: 'maven' + - name: Map JDK Environment Variables + run: | + echo "JDK_8_HOME=$JDK8_HOME" >> $GITHUB_ENV + echo "JDK_11_HOME=$JDK11_HOME" >> $GITHUB_ENV + echo "JDK_17_HOME=$JDK17_HOME" >> $GITHUB_ENV + echo "JDK_21_HOME=$JDK21_HOME" >> $GITHUB_ENV + echo "JDK_25_HOME=$JDK25_HOME" >> $GITHUB_ENV - name: Run ParparVM JVM tests working-directory: vm diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index e60a48aa8e..584918ff88 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -32,11 +32,22 @@ permissions: contents: write pull-requests: write issues: write + packages: read jobs: build-test: runs-on: ubuntu-latest + container: + image: ghcr.io/${{ github.repository_owner }}/codenameone/ci-container:latest + # We need to map the workspace if not done automatically, but actions does it. + # We might need options like --privileged if we needed kvm, but for PR CI we mainly do maven/ant tests. + # However, some tests might need privileges? Usually not unit tests. + options: --user root + defaults: + run: + shell: bash + strategy: fail-fast: false matrix: @@ -44,18 +55,20 @@ jobs: steps: - uses: actions/checkout@v1 - - name: Set up JDK 8 - if: matrix.java-version == 8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - java-package: jdk+fx - - name: Set up JDK - if: matrix.java-version != 8 - uses: actions/setup-java@v4 - with: - distribution: 'zulu' - java-version: ${{ matrix.java-version }} + - name: Configure Java + run: | + if [ "${{ matrix.java-version }}" == "8" ]; then + echo "JAVA_HOME=$JAVA8_HOME" >> $GITHUB_ENV + elif [ "${{ matrix.java-version }}" == "11" ]; then + echo "JAVA_HOME=$JAVA11_HOME" >> $GITHUB_ENV + elif [ "${{ matrix.java-version }}" == "17" ]; then + echo "JAVA_HOME=$JAVA17_HOME" >> $GITHUB_ENV + elif [ "${{ matrix.java-version }}" == "21" ]; then + echo "JAVA_HOME=$JAVA21_HOME" >> $GITHUB_ENV + elif [ "${{ matrix.java-version }}" == "25" ]; then + echo "JAVA_HOME=$JAVA25_HOME" >> $GITHUB_ENV + fi + - name: Cache Maven dependencies uses: actions/cache@v4 with: @@ -73,14 +86,15 @@ jobs: mvn clean verify -DunitTests=true -pl core-unittests -am -Dmaven.javadoc.skip=true -Plocal-dev-javase $MVN_ARGS cd .. - name: Prepare Codename One binaries for Maven plugin tests + # We symlink the container's cn1-binaries to the expected location if tests strictly require it there, + # or we rely on CN1_BINARIES env var. + # The previous step cloned it to maven/target/cn1-binaries. + # We can just point CN1_BINARIES to the container path. run: | - set -euo pipefail - rm -rf maven/target/cn1-binaries - git clone --depth=1 --filter=blob:none https://github.com/codenameone/cn1-binaries maven/target/cn1-binaries + echo "Using pre-installed CN1_BINARIES at $CN1_BINARIES" + - name: Run Maven plugin tests working-directory: maven - env: - CN1_BINARIES: ${{ github.workspace }}/maven/target/cn1-binaries run: | mvn -B -Dmaven.javadoc.skip=true \ -DunitTests=true \ @@ -228,10 +242,11 @@ jobs: await publishQualityComment({ github, context, core }); - name: Install dependencies run: | - sudo apt-get update && sudo apt-get install xvfb - wget https://github.com/codenameone/cn1-binaries/archive/refs/heads/master.zip - unzip master.zip -d .. - mv ../cn1-binaries-master ../cn1-binaries + # Dependencies (xvfb, etc) are already in container. + # cn1-binaries is at $CN1_BINARIES (e.g. /opt/cn1-binaries). + # The legacy build.xml might expect ../cn1-binaries. + # We create a symlink from ../cn1-binaries to $CN1_BINARIES + ln -sf "$CN1_BINARIES" ../cn1-binaries - name: Build CLDC11 JAR run: | ANT_OPTS_ARGS="" diff --git a/Ports/Android/src/com/codename1/impl/android/AndroidScreenshotTask.java b/Ports/Android/src/com/codename1/impl/android/AndroidScreenshotTask.java index f2dfdb6d50..3282678dc4 100644 --- a/Ports/Android/src/com/codename1/impl/android/AndroidScreenshotTask.java +++ b/Ports/Android/src/com/codename1/impl/android/AndroidScreenshotTask.java @@ -73,7 +73,7 @@ public void onPixelCopyFinished(int copyResult) { new Handler(Looper.getMainLooper()) ); } catch (Throwable t) { - // Any unexpected issue → fallback + // Any unexpected issue -> fallback Log.e(t); tryFallbackDraw(w, h); } diff --git a/scripts/android/screenshots/graphics-draw-arc.png b/scripts/android/screenshots/graphics-draw-arc.png index bd4136dcfa..581cdd3e27 100644 Binary files a/scripts/android/screenshots/graphics-draw-arc.png and b/scripts/android/screenshots/graphics-draw-arc.png differ diff --git a/scripts/setup-workspace.sh b/scripts/setup-workspace.sh index ec3f401399..14355ee053 100755 --- a/scripts/setup-workspace.sh +++ b/scripts/setup-workspace.sh @@ -21,9 +21,12 @@ DOWNLOAD_DIR="${TMPDIR%/}/codenameone-tools" ENV_DIR="$DOWNLOAD_DIR/tools" mkdir -p "$DOWNLOAD_DIR" mkdir -p "$ENV_DIR" + CN1_BINARIES_PARENT="$(cd .. && pwd -P)" -CN1_BINARIES="${CN1_BINARIES_PARENT%/}/cn1-binaries" -mkdir -p "$CN1_BINARIES_PARENT" +if [ -z "${CN1_BINARIES:-}" ]; then + CN1_BINARIES="${CN1_BINARIES_PARENT%/}/cn1-binaries" +fi +mkdir -p "$(dirname "$CN1_BINARIES")" ENV_FILE="$ENV_DIR/env.sh" @@ -185,38 +188,42 @@ PATH="$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH" log "Preparing cn1-binaries checkout" if [ -d "$CN1_BINARIES/.git" ]; then log "Found existing cn1-binaries repository at $CN1_BINARIES" - if git -C "$CN1_BINARIES" remote get-url origin >/dev/null 2>&1; then - if git -C "$CN1_BINARIES" fetch --depth=1 origin; then - remote_head=$(git -C "$CN1_BINARIES" symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true) - if [ -z "$remote_head" ]; then - current_branch=$(git -C "$CN1_BINARIES" rev-parse --abbrev-ref HEAD 2>/dev/null || true) - if [ -n "$current_branch" ] && [ "$current_branch" != "HEAD" ]; then - remote_head="origin/$current_branch" - else - remote_head="origin/master" + if [ "${CN1_SKIP_BINARIES_UPDATE:-0}" != "1" ]; then + if git -C "$CN1_BINARIES" remote get-url origin >/dev/null 2>&1; then + if git -C "$CN1_BINARIES" fetch --depth=1 origin; then + remote_head=$(git -C "$CN1_BINARIES" symbolic-ref --quiet --short refs/remotes/origin/HEAD 2>/dev/null || true) + if [ -z "$remote_head" ]; then + current_branch=$(git -C "$CN1_BINARIES" rev-parse --abbrev-ref HEAD 2>/dev/null || true) + if [ -n "$current_branch" ] && [ "$current_branch" != "HEAD" ]; then + remote_head="origin/$current_branch" + else + remote_head="origin/master" + fi fi - fi - if ! git -C "$CN1_BINARIES" rev-parse --verify "$remote_head" >/dev/null 2>&1; then - if git -C "$CN1_BINARIES" rev-parse --verify origin/main >/dev/null 2>&1; then - remote_head="origin/main" - elif git -C "$CN1_BINARIES" rev-parse --verify origin/master >/dev/null 2>&1; then - remote_head="origin/master" - else - log "Unable to determine remote head for cached cn1-binaries; removing checkout" - rm -rf "$CN1_BINARIES" + if ! git -C "$CN1_BINARIES" rev-parse --verify "$remote_head" >/dev/null 2>&1; then + if git -C "$CN1_BINARIES" rev-parse --verify origin/main >/dev/null 2>&1; then + remote_head="origin/main" + elif git -C "$CN1_BINARIES" rev-parse --verify origin/master >/dev/null 2>&1; then + remote_head="origin/master" + else + log "Unable to determine remote head for cached cn1-binaries; removing checkout" + rm -rf "$CN1_BINARIES" + fi fi - fi - if [ -d "$CN1_BINARIES/.git" ]; then - log "Updating cn1-binaries to $remote_head" - git -C "$CN1_BINARIES" reset --hard "$remote_head" + if [ -d "$CN1_BINARIES/.git" ]; then + log "Updating cn1-binaries to $remote_head" + git -C "$CN1_BINARIES" reset --hard "$remote_head" + fi + else + log "Failed to fetch updates for cached cn1-binaries; removing checkout" + rm -rf "$CN1_BINARIES" fi else - log "Failed to fetch updates for cached cn1-binaries; removing checkout" + log "Cached cn1-binaries checkout missing origin remote; removing" rm -rf "$CN1_BINARIES" fi else - log "Cached cn1-binaries checkout missing origin remote; removing" - rm -rf "$CN1_BINARIES" + log "Skipping cn1-binaries update (CN1_SKIP_BINARIES_UPDATE=1)" fi fi