Skip to content

fix(ios): update stale cacert.pem pinned checksum #5098

fix(ios): update stale cacert.pem pinned checksum

fix(ios): update stale cacert.pem pinned checksum #5098

Workflow file for this run

name: Android
on:
push:
branches:
- master
- 'Stable*'
tags:
- 'v*'
paths-ignore:
- 'docs/**'
pull_request:
merge_group:
workflow_dispatch:
inputs:
build_type:
description: 'Build type'
required: false
default: 'Release'
type: choice
options:
- Release
- Debug
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
permissions:
contents: read
actions: read
jobs:
changes:
uses: ./.github/workflows/_detect-changes.yml
with:
platform: android
# The windows leg is the PR long pole by a decent amount; android_matrix.py drops it
# for pull requests and keeps it for push / merge queue / dispatch.
build-matrix:
needs: changes
if: needs.changes.outputs.should_build == 'true'
runs-on: ubuntu-latest
timeout-minutes: 1
outputs:
include: ${{ steps.build.outputs.include }}
steps:
- uses: actions/checkout@v7
with:
sparse-checkout: |
.github/scripts/android_matrix.py
.github/scripts/ci_bootstrap.py
tools/_bootstrap.py
tools/common/__init__.py
tools/common/file_traversal.py
tools/common/gh_actions.py
sparse-checkout-cone-mode: false
fetch-depth: 1
persist-credentials: false
- name: Build matrix
id: build
env:
IS_PR: ${{ github.event_name == 'pull_request' && '1' || '0' }}
run: python3 .github/scripts/android_matrix.py
build:
name: Android (${{ matrix.host }})
needs: [changes, build-matrix]
if: needs.changes.outputs.should_build == 'true'
# RunsOn runners only when the leg defines one, on mavlink, and not from a fork.
runs-on: ${{ github.repository_owner == 'mavlink' && matrix.runson_runner != '' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && format('runs-on={0}/runner={1}', github.run_id, matrix.runson_runner) || matrix.fallback_runner }}
timeout-minutes: 120
# id-token/attestations scoped here: only the "Attest and Upload" step needs them.
permissions:
contents: read
actions: read
id-token: write
attestations: write
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.build-matrix.outputs.include) }}
defaults:
run:
shell: ${{ matrix.shell }}
env:
BUILD_TYPE: ${{ inputs.build_type || 'Release' }}
PACKAGE: QGroundControl
QT_ANDROID_KEYSTORE_PATH: ${{ github.workspace }}/deploy/android/android_release.keystore
QT_ANDROID_KEYSTORE_ALIAS: QGCAndroidKeyStore
QT_ANDROID_KEYSTORE_STORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
QT_ANDROID_KEYSTORE_KEY_PASS: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
QT_ANDROID_ABIS: >-
${{ matrix.emulator && 'x86_64'
|| (matrix.primary && github.event_name != 'pull_request' && github.event_name != 'pull_request_target') && 'arm64-v8a;armeabi-v7a'
|| 'arm64-v8a' }}
HAS_PLAYSTORE_SECRET: ${{ secrets.GOOGLE_SERVICE_ACCOUNT != '' }}
steps:
- name: Enable RunsOn magic cache
if: github.repository_owner == 'mavlink' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && matrix.host != 'mac'
uses: runs-on/action@v2
with:
metrics: cpu,network,memory,disk,io
show_costs: summary
- name: Harden Runner
uses: step-security/harden-runner@v2
with:
egress-policy: audit
- name: Checkout repo
uses: actions/checkout@v7
with:
fetch-depth: ${{ github.event_name == 'pull_request' && 1 || 0 }}
persist-credentials: false
# RunsOn images ship no Android SDK and don't preset ANDROID_SDK_ROOT (unlike
# GitHub-hosted images), so setup-android@v4 has no install target. Point it
# at a writable path. macOS stays GitHub-hosted with its preinstalled SDK.
- name: Set Android SDK location
if: matrix.host != 'mac'
shell: bash
run: |
echo "ANDROID_SDK_ROOT=${RUNNER_TEMP}/android-sdk" >> "$GITHUB_ENV"
echo "ANDROID_HOME=${RUNNER_TEMP}/android-sdk" >> "$GITHUB_ENV"
- name: Build Setup (Android)
id: setup
uses: ./.github/actions/build-setup
with:
mode: android
qt-host: ${{ matrix.qt_host || matrix.host }}
qt-arch: ${{ matrix.arch }}
aqt-source: ${{ matrix.aqt_source || '' }}
abis: ${{ env.QT_ANDROID_ABIS }}
build-type: ${{ env.BUILD_TYPE }}
# matrix.host is unique per leg; linux and linux-emulator otherwise
# resolve to identical cache inputs and would race on the moccache
# save key.
cache-key-suffix: ${{ matrix.host }}
cpm-modules: ${{ runner.temp }}/build/cpm_modules
- name: Install host build dependencies
if: runner.os == 'Linux'
uses: ./.github/actions/install-dependencies
- name: Create Debug Keystore
if: ${{ env.QT_ANDROID_KEYSTORE_STORE_PASS == '' || !matrix.primary }}
shell: bash
run: |
keytool -genkey -v \
-keystore "${RUNNER_TEMP}/debug.keystore" \
-storepass android -alias androiddebugkey -keypass android \
-keyalg RSA -keysize 2048 -validity 10000 \
-dname "CN=Android Debug,O=Android,C=US"
{
echo "QT_ANDROID_KEYSTORE_PATH=${RUNNER_TEMP}/debug.keystore"
echo "QT_ANDROID_KEYSTORE_ALIAS=androiddebugkey"
echo "QT_ANDROID_KEYSTORE_STORE_PASS=android"
echo "QT_ANDROID_KEYSTORE_KEY_PASS=android"
} >> "$GITHUB_ENV"
- name: Configure
uses: ./.github/actions/cmake-configure
with:
build-dir: ${{ runner.temp }}/build
build-type: ${{ env.BUILD_TYPE }}
use-qt-cmake: 'false'
extra-args: >-
-DCMAKE_WARN_DEPRECATED=FALSE
-DCMAKE_TOOLCHAIN_FILE=${{ steps.setup.outputs.target_qt_root_dir }}/lib/cmake/Qt6/qt.toolchain.cmake
-DCMAKE_PREFIX_PATH=${{ steps.setup.outputs.target_qt_root_dir }}
-DQT_ANDROID_ABIS=${{ env.QT_ANDROID_ABIS }}
-DQT_HOST_PATH=${{ steps.setup.outputs.host_qt_root_dir }}
-DQT_ANDROID_SIGN_APK=ON
- name: Build
id: build
continue-on-error: ${{ matrix.emulator }}
timeout-minutes: 75
# Disable Gradle daemon on CI — Windows runners hang for 30+ min after BUILD SUCCESSFUL waiting for daemon shutdown.
env:
GRADLE_OPTS: -Dorg.gradle.daemon=false
uses: ./.github/actions/cmake-build
with:
build-dir: ${{ runner.temp }}/build
build-type: ${{ env.BUILD_TYPE }}
parallel-jobs: ${{ matrix.emulator && '2' || '' }}
output-file: qgc-build.log
- name: Retry Build (emulator JSON truncation recovery)
id: build-retry
if: ${{ matrix.emulator && steps.build.outcome == 'failure' }}
shell: bash
run: |
python3 "${GITHUB_WORKSPACE}/.github/scripts/android_build_retry.py" \
--build-dir "${{ runner.temp }}/build" \
--build-type "${BUILD_TYPE}"
# `failure()` is required: build's continue-on-error makes outcome alone insufficient.
- name: Annotate emulator build retry failure
if: ${{ failure() && matrix.emulator && steps.build.outcome == 'failure' && steps.build-retry.outcome == 'failure' }}
run: echo "::error::Android emulator build failed (initial + retry). See logs for the truncation root cause."
- name: Upload build log on failure
if: ${{ failure() && steps.build.outcome == 'failure' }}
uses: actions/upload-artifact@v7
with:
name: android-${{ matrix.host }}-build-log
path: |
${{ runner.temp }}/build/qgc-build.log
${{ runner.temp }}/build/qgc-build-retry.log
${{ runner.temp }}/build/CMakeFiles/CMakeOutput.log
${{ runner.temp }}/build/CMakeFiles/CMakeError.log
${{ runner.temp }}/build/.ninja_log
${{ runner.temp }}/build/android-QGroundControl-deployment-settings.json
if-no-files-found: ignore
retention-days: 7
- name: Android Lint
if: ${{ matrix.host == 'linux' }}
shell: bash
working-directory: ${{ runner.temp }}/build/android-build
run: |
if [[ ! -x "./gradlew" ]]; then
echo "::error::Gradle wrapper not found in ${PWD}"
ls -la
exit 1
fi
./gradlew lintRelease --no-daemon
- name: Prepare Artifact
shell: bash
run: |
TEMP_DIR="${RUNNER_TEMP//\\//}" # Convert backslashes for Windows
APK_DIR="${TEMP_DIR}/build/android-build"
if ! ls "${APK_DIR}"/*.apk 1>/dev/null 2>&1; then
echo "::error::No APK files found in ${APK_DIR}"
ls -la "${APK_DIR}" 2>/dev/null || echo "Build directory does not exist"
exit 1
fi
cp "${APK_DIR}"/*.apk "${TEMP_DIR}/build/${{ env.PACKAGE }}.apk"
- name: Emulator Boot Test
if: ${{ matrix.emulator }}
uses: ./.github/actions/android-emulator-test
with:
apk-path: ${{ runner.temp }}/build/${{ env.PACKAGE }}.apk
package: org.mavlink.qgroundcontrol
android-platform: ${{ steps.setup.outputs.android_platform }}
qt-version: ${{ steps.setup.outputs.qt_version }}
ndk-version: ${{ steps.setup.outputs.android_ndk_full_version }}
diagnostics-name: ${{ matrix.host }}
- name: Attest and Upload
if: ${{ !matrix.emulator }}
uses: ./.github/actions/attest-and-upload
with:
artifact-name: ${{ env.PACKAGE }}.apk
package-name: ${{ format('{0}-{1}', env.PACKAGE, matrix.host) }}
subject-name: ${{ env.PACKAGE }}-${{ matrix.host }}
aws-role-arn: ${{ secrets.AWS_ROLE_ARN }}
aws-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-distribution-id: ${{ secrets.AWS_DISTRIBUTION_ID }}
upload-aws: ${{ matrix.primary }}
# Shell conditional, not a `&& x || y` GHA ternary whose `||` arm misfires
# if the truthy arm ever evaluates falsy. tag -> production; master -> beta.
- name: Compute Play Store rollout
id: playstore_rollout
if: ${{ !matrix.emulator && matrix.primary && env.HAS_PLAYSTORE_SECRET == 'true' && (github.ref_type == 'tag' || github.ref == 'refs/heads/master') }}
env:
REF_TYPE: ${{ github.ref_type }}
run: |
if [ "${REF_TYPE}" = "tag" ]; then
{ echo "track=production"; echo "status=inProgress"; echo "user_fraction=0.2"; } >> "${GITHUB_OUTPUT}"
else
{ echo "track=beta"; echo "status=completed"; echo "user_fraction="; } >> "${GITHUB_OUTPUT}"
fi
- name: Deploy to Play Store
if: ${{ !matrix.emulator && matrix.primary && env.HAS_PLAYSTORE_SECRET == 'true' && (github.ref_type == 'tag' || github.ref == 'refs/heads/master') }}
uses: ./.github/actions/playstore
with:
artifact: ${{ runner.temp }}/build/${{ env.PACKAGE }}.apk
service_account_json: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }}
track: ${{ steps.playstore_rollout.outputs.track }}
status: ${{ steps.playstore_rollout.outputs.status }}
user_fraction: ${{ steps.playstore_rollout.outputs.user_fraction }}
whats_new_directory: ${{ github.workspace }}/deploy/android/whatsnew