SquirrelJME/SquirrelJME

View on GitHub
.circleci/config.yml

Summary

Maintainability
Test Coverage
# ---------------------------------------------------------------------------
# Multi-Phasic Applications: SquirrelJME
#     Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
#     Copyright (C) Multi-Phasic Applications <multiphasicapps.net>
# ---------------------------------------------------------------------------
# SquirrelJME is under the GNU General Public License v3, or later.
# See license.mkd for licensing and copyright information.
# ---------------------------------------------------------------------------
# DESCRIPTION: CircleCI Build Configuration
# SourceForge: squirreljme@frs.sourceforge.net
# SourceForge Root: /home/frs/project/squirreljme/AutoBuild/
# CircleCI Reference: https://circleci.com/docs/2.0/env-vars/

version: 2.1

executors:
  build-on-linux-amd64:
    #docker:
    #  - image: debian:bookworm
    machine:
      image: ubuntu-2204:2024.01.1
    resource_class: medium
    environment:
      # Allow Gradle to be fully cached
      GRADLE_USER_HOME: ${CIRCLE_WORKING_DIRECTORY}/.gradle/home

      # Fix Debian package install
      DEBIAN_FRONTEND: noninteractive
      NEEDRESTART_MODE: l
      NEEDRESTART_SUSPEND: 1

  build-on-linux-arm64:
    #docker:
    #  - image: debian:bookworm
    machine:
      image: ubuntu-2204:2024.01.1
    resource_class: arm.medium
    environment:
      # Allow Gradle to be fully cached
      GRADLE_USER_HOME: ${CIRCLE_WORKING_DIRECTORY}/.gradle/home

      # Fix Debian package install
      DEBIAN_FRONTEND: noninteractive
      NEEDRESTART_MODE: l
      NEEDRESTART_SUSPEND: 1

  build-on-linux-riscv64:
    machine: true
    resource_class: squirreljme/squirreljme-linux-riscv64

  # This is in the documentation but does not actually work, new feature?
  #  build-on-windows:
  #    windows:
  #      name: win/default
  #      shell: cmd.exe
  #    resource_class: medium
  #    environment:
  #      # Use a reduced amount of memory to all the VMs so that it does not
  #      # try grabbing all the memory that is available to the system.
  #      JAVA_OPTS: -Xmx3g

  build-on-macos:
    machine: true
    resource_class: squirreljme/squirreljme-macos-x86

  build-on-macos-m1:
    machine: true
    resource_class: squirreljme/squirreljme-macos-m1

orbs:
  win: circleci/windows@5.0

# Parameters to simplify commands
parameters:
  # Options to be used for any Gradle command, is faster this way
  standard-gradle-options:
    type: string
    default: --console plain --continue --parallel --no-daemon --stacktrace

  # Standard build for systems
  standard-build-options:
    type: string
    default: build testHosted -x testSpringCoat -x testSpringCoatRelease -x testSpringCoatDebug -x javadoc -x javadocJar -x sourcesJar -x markdownJavaDoc

# Commands that are used by almost everything
commands:
  # Save Gradle cache and such so subsequent builds are faster
  persist-gradle:
    steps:
      - persist_to_workspace:
          root: .
          paths:
            - '.gradle/*'
            - 'build/*'
            - '*/.gradle/*'
            - '*/build/*'
            - '*/*/build/*'

  # Saving of test results, since this is duplicated for many OSes
  save-test-results:
    parameters:
      where:
        type: string
      os:
        type: string
      vm:
        type: string
      shell:
        type: string
        default: "/bin/bash"
      home:
        type: string
        default: ./.no-persist/
      find:
        type: string
        default: find
      store-home:
        type: string
        default: ./.no-persist/
    steps:
      - run:
          shell: <<parameters.shell>>
          name: Save test results
          command: |
            mkdir -p "<<parameters.home>>/test-results/junit-<<parameters.os>>-<<parameters.where>>/"
            <<parameters.find>> . -type f -regex '.*/'"<<parameters.where>>"'/junit/.*\.xml' -exec cp {} "<<parameters.home>>/test-results/junit-<<parameters.os>>-<<parameters.where>>/" \;
          when: always
      - run:
          shell: <<parameters.shell>>
          name: Save test results
          command: |
            mkdir -p "<<parameters.home>>/test-results/csv-<<parameters.os>>-<<parameters.where>>/"
            <<parameters.find>> . -type f -regex '.*/'"<<parameters.where>>"'/csv/.*\.csv' -exec cp {} "<<parameters.home>>/test-results/csv-<<parameters.os>>-<<parameters.where>>/" \;
          when: always
      - run:
          shell: <<parameters.shell>>
          name: Save snapshots
          command: |
            mkdir -p "<<parameters.home>>/test-results/nps-<<parameters.vm>>-<<parameters.os>>-<<parameters.where>>/"
            <<parameters.find>> . -type f -regex '.*/'"<<parameters.where>>"'/nps/.*\.nps' -exec cp {} "<<parameters.home>>/test-results/nps-<<parameters.vm>>-<<parameters.os>>-<<parameters.where>>/" \;
          when: always
      - store_test_results:
          path: <<parameters.store-home>>/test-results
      - store_artifacts:
          path: <<parameters.store-home>>/test-results

  # Standard apt-get install
  linux-debian-apt-get-install:
    parameters:
      packages:
        type: string
    steps:
      - run:
          name: Install packages
          environment:
            DEBIAN_FRONTEND: noninteractive
            NEEDRESTART_MODE: l
            NEEDRESTART_SUSPEND: 1
          command: |
            sudo apt-get install -y --no-install-recommends <<parameters.packages>>

  # Install standard packages in Debian/Ubuntu
  linux-install-required:
    steps:
      - run:
          name: Install Sudo
          environment:
            DEBIAN_FRONTEND: noninteractive
            NEEDRESTART_MODE: l
            NEEDRESTART_SUSPEND: 1
          command: apt-get update -y && apt-get -yqq install sudo || echo "Failed, but ignoring..."
      - run:
          name: Update package lists
          environment:
            DEBIAN_FRONTEND: noninteractive
            NEEDRESTART_MODE: l
            NEEDRESTART_SUSPEND: 1
          command: sudo apt-get update -y
      - linux-debian-apt-get-install:
          packages: cmake build-essential curl wget openjdk-17-jdk gcc g++ make clang git openssh-client

  # Install required packages on Windows
  windows-install-required:
    steps:
      - run:
          name: Install CMake
          shell: cmd.exe
          command: choco install cmake -y

  # Install required packages on macOS
  macos-install-required:
    steps:
      - run:
          # Only OpenJDK is required, Gradle always uses Gradle wrapper so
          # we do not need that... also CMake as well for native code
          name: Install Dependencies
          command: brew install openjdk@11 coreutils cmake

  # Install what is required by Flatpak
  flatpak-install-required:
    steps:
      - linux-debian-apt-get-install:
          packages: flatpak flatpak-builder
      - run:
          name: Register Flathub
          command: flatpak remote-add --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo
      - run:
          name: Flatpak FreeDesktop Platform
          command: flatpak install --user -y --noninteractive flathub org.freedesktop.Platform//23.08
      - run:
          name: Flatpak FreeDesktop SDK
          command: flatpak install --user -y --noninteractive flathub org.freedesktop.Sdk//23.08
      - run:
          name: Flatpak OpenJDK
          command: flatpak install --user -y --noninteractive flathub runtime/org.freedesktop.Sdk.Extension.openjdk11//23.08

  # Flatpak Common Build Rules
  flatpak-common-build:
    parameters:
      arch:
        type: string
    steps:
      - run:
          name: Flatpak Build and Install
          command: flatpak-builder --user --install --install-deps-from=flathub --allow-missing-runtimes --force-clean build-dir cc.squirreljme.SquirrelJME.yml
      - run:
          name: Flatpak Bundle
          command: flatpak build-bundle $HOME/.local/share/flatpak/repo squirreljme-<<parameters.arch>>.flatpak cc.squirreljme.SquirrelJME
      - run:
          name: Flatpak size
          command: ls -al squirreljme-<<parameters.arch>>.flatpak
      - store_artifacts:
          path: squirreljme-<<parameters.arch>>.flatpak
          destination: squirreljme-<<parameters.arch>>.flatpak

  # Common Build for Standalone (UNIX)
  standalone-unix-common-build:
    steps:
      - run:
          name: Construct Standalone
          command: ./gradlew :emulators:standalone:shadowJar <<pipeline.parameters.standard-gradle-options>>
      - run:
          name: Remove distracting JAR, if any
          command: rm emulators/standalone/build/libs/standalone-*.jar
      - store_artifacts:
          path: emulators/standalone/build/libs/
          destination: .

jobs:
  ################################## BUNDLE ##################################
  bundle:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required

  ################################## WINDOWS #################################
  build_windows_setup:
    executor:
      name: win/default
      shell: cmd.exe
      size: medium
    environment:
      # Use older JDK for CircleCI
      JAVA_HOME: c:/users/circleci/project/jdk-11.0.22/
    steps:
      - run:
          shell: bash.exe
          name: Download Older JDK
          command: curl -o /c/users/circleci/jdk.zip https://download.bell-sw.com/java/11.0.22+12/bellsoft-jdk11.0.22+12-windows-amd64.zip
      - run:
          shell: bash.exe
          name: Extract Older JDK
          command: unzip /c/users/circleci/jdk.zip
      - run:
          shell: cmd.exe
          name: Java Version
          command: java -version
      - persist_to_workspace:
          root: .
          paths:
            - 'jdk-11.0.22/'
  build_windows:
    executor:
      name: win/default
      shell: cmd.exe
      size: medium
    environment:
      # Use a reduced amount of memory to all the VMs so that it does not
      # try grabbing all the memory that is available to the system.
      JAVA_OPTS: -Xmx3g

      # Use older JDK for CircleCI
      JAVA_HOME: c:/users/circleci/project/jdk-11.0.22/
    steps:
      - checkout
      - attach_workspace:
          at: .
      - windows-install-required
      - run:
          shell: cmd.exe
          name: Java Version
          command: java -version
      - run:
          shell: cmd.exe
          name: Gradle Build and Test
          # According to documentation, Gradle on Windows has trouble and tries
          # to make way too many workers which causes extreme resource.
          # contention --max-workers=2
          command: gradlew <<pipeline.parameters.standard-build-options>> <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 60m
      - persist-gradle
      - save-test-results:
          where: "vm-test-hosted-debug"
          os: "windows"
          vm: "hosted"
          shell: bash.exe
          find: /usr/bin/find
          home: "/c/users/circleci/"
          store-home: "c:/users/circleci/"
      - save-test-results:
          where: "vm-test-hosted-release"
          os: "windows"
          vm: "hosted"
          shell: bash.exe
          find: /usr/bin/find
          home: "/c/users/circleci/"
          store-home: "c:/users/circleci/"

  build_windows_standalone:
    executor:
      name: win/default
      shell: cmd.exe
      size: medium
    environment:
      # Use a reduced amount of memory to all the VMs so that it does not
      # try grabbing all the memory that is available to the system.
      JAVA_OPTS: -Xmx3g

      # Use older JDK for CircleCI
      JAVA_HOME: c:/users/circleci/project/jdk-11.0.22/
    steps:
      - checkout
      - attach_workspace:
          at: .
      - windows-install-required
      - run:
          shell: bash.exe
          name: Construct Standalone
          command: ./gradlew :emulators:standalone:shadowJar <<pipeline.parameters.standard-gradle-options >>
      - run:
          shell: bash.exe
          name: Remove distracting JAR, if any
          command: rm emulators/standalone/build/libs/standalone-*.jar
      - store_artifacts:
          path: emulators/standalone/build/libs/
          destination: .

  ################################# MAC OS X #################################
  build_macosx:
    executor: build-on-macos
    steps:
      - checkout
      - run:
          name: Gradle Build and Test
          command: timeout --foreground 60m ./gradlew <<pipeline.parameters.standard-build-options>> <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 60m
      - persist-gradle
      - save-test-results:
          where: "vm-test-hosted-debug"
          os: "macosx"
          vm: "hosted"
      - save-test-results:
          where: "vm-test-hosted-release"
          os: "macosx"
          vm: "hosted"
  build_macosx_m1:
    executor: build-on-macos-m1
    steps:
      - checkout
      - run:
          name: Gradle Build and Test
          command: timeout --foreground 60m ./gradlew <<pipeline.parameters.standard-build-options>> <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 60m
      - persist-gradle
      - save-test-results:
          where: "vm-test-hosted-debug"
          os: "macosx-m1"
          vm: "hosted"
      - save-test-results:
          where: "vm-test-hosted-release"
          os: "macosx-m1"
          vm: "hosted"

  build_macosx_standalone:
    executor: build-on-macos
    steps:
      - checkout
      - attach_workspace:
          at: .
      - standalone-unix-common-build
  build_macosx_m1_standalone:
    executor: build-on-macos-m1
    steps:
      - checkout
      - attach_workspace:
          at: .
      - standalone-unix-common-build

  ################################### LINUX ##################################
  # Linux AMD64
  build_linux_amd64:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - run:
          name: Gradle Build and Test
          command: timeout --foreground 60m ./gradlew <<pipeline.parameters.standard-build-options>> <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 60m
      - save-test-results:
          where: "vm-test-hosted-debug"
          os: "linux-amd64"
          vm: "hosted"
      - save-test-results:
          where: "vm-test-hosted-release"
          os: "linux-amd64"
          vm: "hosted"
      - persist-gradle
  build_linux_amd64_standalone:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - attach_workspace:
          at: .
      - standalone-unix-common-build
  build_linux_amd64_standalone_flatpak:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - flatpak-install-required
      - flatpak-common-build:
          arch: amd64

  # Linux ARM64
  build_linux_arm64:
    executor: build-on-linux-arm64
    steps:
      - checkout
      - linux-install-required
      - run:
          name: Gradle Build and Test
          command: timeout --foreground 60m ./gradlew <<pipeline.parameters.standard-build-options>> <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 60m
      - save-test-results:
          where: "vm-test-hosted-debug"
          os: "linux-arm64"
          vm: "hosted"
      - save-test-results:
          where: "vm-test-hosted-release"
          os: "linux-arm64"
          vm: "hosted"
      - persist-gradle
  build_linux_arm64_standalone:
    executor: build-on-linux-arm64
    steps:
      - checkout
      - linux-install-required
      - attach_workspace:
          at: .
      - standalone-unix-common-build
  build_linux_arm64_standalone_flatpak:
    executor: build-on-linux-arm64
    steps:
      - checkout
      - linux-install-required
      - flatpak-install-required
      - flatpak-common-build:
          arch: arm64

  # Linux RISC-V 64-bit
  build_linux_riscv64:
    executor: build-on-linux-riscv64
    steps:
      - checkout
      - run:
          name: Gradle Build and Test
          command: timeout --foreground 120m ./gradlew <<pipeline.parameters.standard-build-options>> <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 120m
      - save-test-results:
          where: "vm-test-hosted-debug"
          os: "linux-arm64"
          vm: "hosted"
      - save-test-results:
          where: "vm-test-hosted-release"
          os: "linux-arm64"
          vm: "hosted"
      - persist-gradle
  build_linux_riscv64_standalone:
    executor: build-on-linux-riscv64
    steps:
      - checkout
      - attach_workspace:
          at: .
      - standalone-unix-common-build

  ### OSS SonaType Nexus
  sonatype_publish:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - attach_workspace:
          at: .
      - run:
          name: Publish to OSS SonaType
          command: ./gradlew publishMavenPublicationToMavenRepository <<pipeline.parameters.standard-gradle-options>> || circleci-agent step halt

  ### SpringCoat
  test_springcoat_debug:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - attach_workspace:
          at: .
      - run:
          name: SpringCoat Tests
          command: timeout --foreground 60m ./gradlew testSpringCoatDebug <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 60m
      - save-test-results:
          where: "vm-test-springcoat-debug"
          os: "linux"
          vm: "springcoat"
  test_springcoat_release:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - attach_workspace:
          at: .
      - run:
          name: SpringCoat Tests
          command: timeout --foreground 60m ./gradlew testSpringCoatRelease <<pipeline.parameters.standard-gradle-options>>
          no_output_timeout: 60m
      - save-test-results:
          where: "vm-test-springcoat-release"
          os: "linux"
          vm: "springcoat"

  ################################### USERS ##################################
  export_user_guide:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - run:
          name: Checkout Wiki
          command: git clone git@github.com:SquirrelJME/SquirrelJME.wiki.git /tmp/wiki
      - run:
          name: Wikify
          command: .circleci/squirreljme-wikify-user-guide.sh "$(pwd)" "/tmp/wiki"
      - run:
          name: Update Git User
          command: |
            cd "/tmp/wiki" && git config user.name "SquirrelJME Automation" && git config user.email "xerthesquirrel+squirreljme@gmail.com"
      - run:
          name: Commit changes
          command: |
            cd "/tmp/wiki" && git commit -m "Synchronize User-Guide" || echo "Ignoring commit."
      - add_ssh_keys:
          fingerprints:
            - "26:b8:ae:4d:53:64:4c:6a:59:3d:a6:60:44:90:9d:6c"
      - run:
          name: Push changes
          command: |
            cd "/tmp/wiki" && git push

  ################################ CONSTRUCTION ###############################
  # Runs the `testJar` task so any operations following this will run faster
  # when they need to use these JARs
  construct_testJars:
    executor: build-on-linux-amd64
    steps:
      - checkout
      - linux-install-required
      - attach_workspace:
          at: .
      - run:
          name: Construct Test JARs
          command: ./gradlew testJar <<pipeline.parameters.standard-gradle-options>>
      - persist-gradle

workflows:
  version: 2
  tests:
    jobs:
      ############################# STANDARD TESTS ############################
      # AMD64
      - build_linux_amd64
      - test_springcoat_debug:
          requires:
            - construct_testJars
      - test_springcoat_release:
          requires:
            - construct_testJars
          filters:
            branches:
              only:
                - trunk
      - build_linux_amd64_standalone:
          requires:
            - build_linux_amd64
          filters:
            branches:
              only:
                - trunk
      - build_linux_amd64_standalone_flatpak:
          requires:
            - build_linux_amd64
          filters:
            branches:
              only:
                - trunk

      # ARM64
      - build_linux_arm64
      - build_linux_arm64_standalone:
          requires:
            - build_linux_arm64
          filters:
            branches:
              only:
                - trunk
      - build_linux_arm64_standalone_flatpak:
          requires:
            - build_linux_arm64
          filters:
            branches:
              only:
                - trunk

      # RISC-V 64-bit
#      - build_linux_riscv64
#      - build_linux_riscv64_standalone:
#          requires:
#            - build_linux_riscv64
#          filters:
#            branches:
#              only:
#                - trunk

      # Building on Windows is currently expensive and takes longer, so only
      # run these builds on trunk to lower costs.
      # Currently, have an overabundance of credits...
      - build_windows_setup
      - build_windows:
          requires:
            - build_windows_setup
      - build_windows_standalone:
          requires:
            - build_windows
          filters:
            branches:
              only:
                - trunk

      # Mac OS X runs decently however the jobs for it have a higher cost, so
      # only perform builds and tests for trunk to lower costs.
      # Currently, I have an overabundance of credits...
      - build_macosx
      - build_macosx_m1
      - build_macosx_standalone:
          requires:
            - build_macosx
          filters:
            branches:
              only:
                - trunk
      - build_macosx_m1_standalone:
          requires:
            - build_macosx_m1
          filters:
            branches:
              only:
                - trunk

      # Publishing to OSS Sonatype Nexus (https://oss.sonatype.org)
      - sonatype_publish:
          requires:
            - build_linux_amd64
          filters:
            branches:
              only:
                - trunk
                - wip-centralpublish

      ###################### LIBRARY AND ROM CONSTRUCTION #####################
      - construct_testJars:
          requires:
            - build_linux_amd64

      ############################## DEPLOYMENT ##############################
      - bundle:
          requires:
            - build_linux_amd64_standalone
            - build_windows_standalone
            - build_macosx_standalone
            - build_macosx_m1_standalone
          filters:
            branches:
              only:
                - trunk

  #################### TASKS TO INCREASE USER FRIENDLINESS ####################
  friendliness:
    jobs:
      - export_user_guide:
          filters:
            branches:
              only:
                - trunk
                - wip-userguide