diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 8d8fb2557..668722065 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -16,7 +16,7 @@ on:
       - 'static/**'
       - '*.md'
     tags:
-      - '[0-9]+.[0-9]+.[0-9]+*'
+      - '[0-9]+.[0-9]+.[0-9]+*'   
   workflow_dispatch:
     inputs:
       paid-runners:
@@ -133,11 +133,22 @@ env:
           name: macOS_arm64_dmg
         - path: '*macOS_arm64.zip'
           name: macOS_arm64_zip
+    - config:
+        name: ARM Ubuntu 22.04
+        runs-on: ubuntu-22.04-arm
+        container: |
+          null
+        job-transfer-artifact-suffix: ARM_64bit
+        mergeable-channel-file: 'true'
+      artifacts:
+        - path: '*Linux_arm64.zip'
+          name: Linux_arm64_zip
+        - path: '*Linux_arm64.AppImage'
+          name: Linux_arm64_app_image
   PAID_RUNNER_BUILD_DATA: |
     # This system was implemented to allow selective use of paid GitHub-hosted runners, due to the Apple Silicon runner
     # incurring a charge at that time. Free Apple Silicon runners are now available so the configuration was moved to
     # `BASE_BUILD_DATA`, but the system was left in place for future use.
-
 jobs:
   run-determination:
     runs-on: ubuntu-latest
@@ -160,9 +171,7 @@ jobs:
             # There is no need to run the other jobs.
             RESULT="false"
           fi
-
           echo "result=$RESULT" >> $GITHUB_OUTPUT
-
   build-type-determination:
     needs: run-determination
     if: needs.run-determination.outputs.result == 'true'
@@ -199,13 +208,11 @@ jobs:
             is_nightly="false"
             channel_name="nightly"
           fi
-
           echo "is-release=$is_release" >> $GITHUB_OUTPUT
           echo "is-nightly=$is_nightly" >> $GITHUB_OUTPUT
           echo "channel-name=$channel_name" >> $GITHUB_OUTPUT
           # Only attempt upload to Amazon S3 if the credentials are available.
           echo "publish-to-s3=${{ secrets.AWS_ROLE_ARN != '' }}" >> $GITHUB_OUTPUT
-
   select-targets:
     needs: build-type-determination
     runs-on: ubuntu-latest
@@ -232,7 +239,6 @@ jobs:
                 --output-format json \
                 '[.[].config]'
             )"
-
             artifact_matrix="$(
               (
                 echo "${{ env.BASE_BUILD_DATA }}";
@@ -242,11 +248,9 @@ jobs:
                 --output-format json \
                 'map(.artifacts[] + (.config | pick(["job-transfer-artifact-suffix"])))'
             )"
-
             # The build matrix produces two macOS jobs (x86 and ARM) so the "channel update info files"
             # generated by each must be merged.
             merge_channel_files="true"
-
           else
             build_matrix="$(
               echo "${{ env.BASE_BUILD_DATA }}" | \
@@ -254,31 +258,25 @@ jobs:
                 --output-format json \
                 '[.[].config]'
             )"
-
             artifact_matrix="$(
               echo "${{ env.BASE_BUILD_DATA }}" | \
               yq \
                 --output-format json \
                 'map(.artifacts[] + (.config | pick(["job-transfer-artifact-suffix"])))'
             )"
-
             merge_channel_files="false"
           fi
-
           # Set workflow step outputs.
           # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
           delimiter="$RANDOM"
           echo "build-matrix<<$delimiter" >> $GITHUB_OUTPUT
           echo "$build_matrix" >> $GITHUB_OUTPUT
           echo "$delimiter" >> $GITHUB_OUTPUT
-
           delimiter="$RANDOM"
           echo "artifact-matrix<<$delimiter" >> $GITHUB_OUTPUT
           echo "$artifact_matrix" >> $GITHUB_OUTPUT
           echo "$delimiter" >> $GITHUB_OUTPUT
-
           echo "merge-channel-files=$merge_channel_files" >> $GITHUB_OUTPUT
-
   build:
     name: build (${{ matrix.config.name }})
     needs:
@@ -290,7 +288,7 @@ jobs:
       # to skip passing signing credentials to electron-builder
       IS_WINDOWS_CONFIG: ${{ matrix.config.name == 'Windows' }}
       INSTALLER_CERT_WINDOWS_CER: "/tmp/cert.cer"
-      # We are hardcoding the path for signtool because is not present on the windows PATH env var by default.
+      # We are hardcoding the path for signtool because it is not present on the Windows PATH env var by default.
       # Keep in mind that this path could change when upgrading to a new runner version
       SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.19041.0/x86/signtool.exe"
       WIN_CERT_PASSWORD: ${{ secrets[matrix.config.certificate-password-secret] }}
@@ -310,16 +308,18 @@ jobs:
     timeout-minutes: 90
 
     steps:
+      - name: Install Chromium (ARM only)
+        if: matrix.config.name == 'ARM Ubuntu 22.04'
+        run: sudo apt-get update && sudo apt-get install -y chromium-browser
+
       - name: Symlink custom working directory
         shell: cmd
         if: runner.os == 'Windows' && matrix.config.working-directory
         run: |
           if not exist "${{ matrix.config.working-directory }}" mklink /d "${{ matrix.config.working-directory }}" "C:\actions-runner\_work\arduino-ide\arduino-ide"
-
       - name: Checkout
         uses: actions/checkout@v4
 
-
       - name: Install Node.js
         if: runner.name != 'WINDOWS-SIGN-PC'
         uses: actions/setup-node@v4
@@ -337,7 +337,6 @@ jobs:
             install \
               --global \
               "yarn@${{ env.YARN_VERSION }}"
-
       - name: Install Python 3.x
         if: fromJSON(matrix.config.container) == null && runner.name != 'WINDOWS-SIGN-PC'
         uses: actions/setup-python@v5
@@ -377,15 +376,12 @@ jobs:
             export CSC_KEY_PASSWORD="${{ secrets[matrix.config.certificate-password-secret] }}"
             export CSC_FOR_PULL_REQUEST=true
           fi
-
           npx node-gyp install
           yarn install
-
           yarn --cwd arduino-ide-extension build
           yarn --cwd electron-app rebuild
           yarn --cwd electron-app build
           yarn --cwd electron-app package
-
       # Both macOS jobs generate a "channel update info file" with same path and name. The second job to complete would
       # overwrite the file generated by the first in the workflow artifact.
       - name: Stage channel file for merge
@@ -399,11 +395,9 @@ jobs:
           mv \
             "${{ env.BUILD_ARTIFACTS_PATH }}/${{ needs.build-type-determination.outputs.channel-name }}-mac.yml" \
             "${staged_channel_files_path}/${{ needs.build-type-determination.outputs.channel-name }}-mac-${{ runner.arch }}.yml"
-
           # Set workflow environment variable for use in other steps.
           # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable
           echo "STAGED_CHANNEL_FILES_PATH=$staged_channel_files_path" >> "$GITHUB_ENV"
-
       - name: Upload staged-for-merge channel file artifact
         uses: actions/upload-artifact@v4
         if: >
@@ -425,7 +419,6 @@ jobs:
         shell: cmd
         run: |
           rmdir /s /q "${{ matrix.config.working-directory }}\${{ env.BUILD_ARTIFACTS_PATH }}"
-
   merge-channel-files:
     needs:
       - build-type-determination
@@ -439,7 +432,6 @@ jobs:
         run: |
           # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#setting-an-environment-variable
           echo "CHANNEL_FILES_PATH=${{ runner.temp }}/channel-files" >> "$GITHUB_ENV"
-
       - name: Checkout
         uses: actions/checkout@v4
 
@@ -478,7 +470,6 @@ jobs:
         run: |
           sudo apt-get update
           sudo apt-get install -y libx11-dev libxkbfile-dev libsecret-1-dev
-
       - name: Install dependencies
         run: yarn
 
@@ -488,7 +479,6 @@ jobs:
             ./scripts/merge-channel-files.js \
               --channel "${{ needs.build-type-determination.outputs.channel-name }}" \
               --input "${{ env.CHANNEL_FILES_PATH }}"
-
       - name: Upload merged channel files job transfer artifact
         uses: actions/upload-artifact@v4
         with:
@@ -555,16 +545,13 @@ jobs:
             fi
           fi
           echo -e "$BODY"
-
           # Set workflow step output
           # See: https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
           DELIMITER="$RANDOM"
           echo "BODY<<$DELIMITER" >> $GITHUB_OUTPUT
           echo "$BODY" >> $GITHUB_OUTPUT
           echo "$DELIMITER" >> $GITHUB_OUTPUT
-
           echo "$BODY" > CHANGELOG.txt
-
       - name: Upload changelog job transfer artifact
         if: needs.build-type-determination.outputs.is-nightly == 'true'
         uses: actions/upload-artifact@v4
@@ -615,7 +602,6 @@ jobs:
       - name: Publish Nightly [S3]
         run: |
           aws s3 sync ${{ env.ARTIFACTS_FOLDER }} s3://${{ secrets.DOWNLOADS_BUCKET }}/arduino-ide/nightly
-
   release:
     needs:
       - build-type-determination
@@ -653,7 +639,6 @@ jobs:
         id: tag_name
         run: |
           echo "TAG_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
-
       - name: Publish Release [GitHub]
         uses: svenstaro/upload-release-action@2.9.0
         with:
@@ -675,7 +660,6 @@ jobs:
         if: needs.build-type-determination.outputs.publish-to-s3 == 'true'
         run: |
           aws s3 sync ${{ env.ARTIFACTS_FOLDER }} s3://${{ secrets.DOWNLOADS_BUCKET }}/arduino-ide
-
   clean:
     # This job must run after all jobs that use the transfer artifact.
     needs:
diff --git a/.github/workflows/test-javascript.yml b/.github/workflows/test-javascript.yml
index a1665f4f5..04ff2e861 100644
--- a/.github/workflows/test-javascript.yml
+++ b/.github/workflows/test-javascript.yml
@@ -79,6 +79,7 @@ jobs:
           - macos-latest
           - ubuntu-latest
           - windows-latest
+          - ubuntu-22.04-arm
 
     steps:
       - name: Checkout