servo/.github/workflows/ohos.yml
shuppy 25147c75cb
ci: Stop using python3 ./mach (#39271)
this way of invoking mach is incorrect now that we use uv, and it will
prevent us from running bencher builds on self-hosted runners (#39269),
where the system Python is too old (3.10 vs 3.11).

Testing:
- mach try bencher
<https://github.com/servo/servo/actions/runs/17675086579>

Fixes: part of #39269

Signed-off-by: Delan Azabani <dazabani@igalia.com>
2025-09-12 14:45:31 +00:00

344 lines
16 KiB
YAML

name: OpenHarmony
on:
workflow_call:
inputs:
profile:
required: false
default: "release"
type: string
upload:
required: false
default: false
type: boolean
github-release-id:
required: false
type: string
bencher:
required: false
default: false
type: boolean
workflow_dispatch:
inputs:
profile:
required: false
default: "release"
type: choice
description: "Cargo build profile"
options: ["release", "debug", "production"]
bencher:
required: false
default: false
type: boolean
env:
RUST_BACKTRACE: 1
SHELL: /bin/bash
CARGO_INCREMENTAL: 0
BENCHER_PROJECT: ${{ vars.BENCHER_PROJECT || 'servo' }}
HITRACE_BENCH_VERSION: 0.8.2
jobs:
build:
name: OpenHarmony Build
runs-on: ubuntu-22.04
strategy:
matrix:
target: ["aarch64-unknown-linux-ohos", "x86_64-unknown-linux-ohos"]
outputs:
signed: ${{ steps.signing_config.outputs.signed }}
steps:
- uses: actions/checkout@v4
if: github.event_name != 'pull_request_target'
with:
fetch-depth: 2
# This is necessary to checkout the pull request if this run was triggered via a
# `pull_request_target` event.
- uses: actions/checkout@v4
if: github.event_name == 'pull_request_target'
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 2
- name: Install crown
run: cargo install --path support/crown
- name: Setup Python
uses: ./.github/actions/setup-python
- name: Bootstrap dependencies
run: sudo apt update && ./mach bootstrap --skip-lints
- name: Setup OpenHarmony SDK
id: setup_sdk
uses: openharmony-rs/setup-ohos-sdk@v0.2.3
with:
version: "5.0.2"
fixup-path: true
- name: Install node for hvigor
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install hvigor modules
run: |
mkdir ~/hvigor-installation
cd ~/hvigor-installation
echo "@ohos:registry=https://repo.harmonyos.com/npm/" > .npmrc
npm install "@ohos/hvigor@5" "@ohos/hvigor-ohos-plugin@5"
echo "HVIGOR_PATH=$PWD" >> $GITHUB_ENV
- name: "Setup HAP signing config"
id: signing_config
env:
SIGNING_MATERIAL: ${{ secrets.SERVO_OHOS_SIGNING_MATERIAL }}
if: ${{ inputs.upload || env.SIGNING_MATERIAL != '' }} # Allows the build to pass on forks.
run: |
cd ~
echo "${SIGNING_MATERIAL}" | base64 -d > servo-ohos-material.zip
unzip servo-ohos-material.zip
echo "SERVO_OHOS_SIGNING_CONFIG=${PWD}/servo-ohos-material/signing-configs.json" >> $GITHUB_ENV
echo "signed=true" >> "$GITHUB_OUTPUT"
- name: Build (arch ${{ matrix.target }} profile ${{ inputs.profile }})
env:
OHOS_SDK_NATIVE: ${{ steps.setup_sdk.outputs.ohos_sdk_native }}
OHOS_BASE_SDK_HOME: ${{ steps.setup_sdk.outputs.ohos-base-sdk-home }}
run: |
./mach build --locked --target ${{ matrix.target }} --${{ inputs.profile }}
cp -r target/cargo-timings target/cargo-timings-ohos-${{ matrix.target }}
- name: Archive build timing
uses: actions/upload-artifact@v4
with:
name: cargo-timings-ohos-${{ matrix.target }}-${{ inputs.profile }}
# Using a wildcard here ensures that the archive includes the path.
path: target/cargo-timings-*
- name: Upload nightly
if: ${{ inputs.upload && contains(matrix.target, 'aarch64') }}
run: |
./mach upload-nightly ohos \
--secret-from-environment \
--github-release-id ${{ inputs.github-release-id }}
env:
S3_UPLOAD_CREDENTIALS: ${{ secrets.S3_UPLOAD_CREDENTIALS }}
NIGHTLY_REPO_TOKEN: ${{ secrets.NIGHTLY_REPO_TOKEN }}
NIGHTLY_REPO: ${{ github.repository_owner }}/servo-nightly-builds
- name: Generate artifact attestation for HAP
if: ${{ inputs.upload }}
uses: actions/attest-build-provenance@v1
with:
subject-path: target/openharmony/${{ matrix.target }}/${{ inputs.profile }}/entry/build/default/outputs/default/servoshell-default-signed.hap
- name: Upload signed HAP artifact
if: ${{ env.SERVO_OHOS_SIGNING_CONFIG != '' }} # Build output has different name if not signed.
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.profile }}-binary-ohos-${{ matrix.target }}
path: target/openharmony/${{ matrix.target }}/${{ inputs.profile }}/entry/build/default/outputs/default/servoshell-default-signed.hap
- name: Upload unsigned HAP artifact
if: ${{ env.SERVO_OHOS_SIGNING_CONFIG == '' }} # Build output has different name if not signed.
uses: actions/upload-artifact@v4
with:
name: ${{ inputs.profile }}-binary-ohos-${{ matrix.target }}
path: target/openharmony/${{ matrix.target }}/${{ inputs.profile }}/entry/build/default/outputs/default/servoshell-default-unsigned.hap
bencher:
needs: ["build"]
strategy:
matrix:
target: ["aarch64-unknown-linux-ohos", "x86_64-unknown-linux-ohos"]
if: ${{ inputs.bencher && inputs.profile != 'debug' && github.event_name != 'workflow_dispatch' && github.event_name != 'merge_group' }}
uses: ./.github/workflows/bencher.yml
with:
target: ohos-${{ matrix.target }}
profile: ${{ inputs.profile }}
compressed-file-path: ${{ inputs.profile }}-binary-ohos-${{ matrix.target }}/servoshell-default-${{ needs.build.outputs.signed && 'signed' || 'unsigned' }}.hap
binary-path: libs/${{ matrix.target == 'aarch64-unknown-linux-ohos' && 'arm64-v8a' || matrix.target == 'x86_64-unknown-linux-ohos' && 'x86_64' }}/libservoshell.so
file-size: true
speedometer: false
dromaeo: false
secrets: inherit
# Note: We could potentially also merge this build job with the above one,
# if we figure out how to make hvigor build for harmonyos without the HOS commandline-tools installed.
build-harmonyos-aarch64:
name: HarmonyOS Build (aarch64)
continue-on-error: true
runs-on: hos-builder
if: github.repository == 'servo/servo'
steps:
- if: ${{ github.event_name != 'pull_request_target' }}
run: git fetch --depth=1 origin $GITHUB_SHA
- if: ${{ github.event_name == 'pull_request_target' }}
run: git fetch --depth=1 origin ${{ github.event.pull_request.head.sha }}
- run: |
git switch --detach
git reset --hard FETCH_HEAD
- name: Adding test files to directory
run: cp -r support/hitrace-bencher/* support/openharmony/AppScope/resources/resfile/
- name: Build for aarch64 HarmonyOS
run: |
./mach build --locked --target aarch64-unknown-linux-ohos --profile=${{ inputs.profile }} --flavor=harmonyos --no-default-features --features tracing,tracing-hitrace
- uses: actions/upload-artifact@v4
with:
# Upload the **unsigned** artifact - We don't have the signing materials in pull request workflows
name: servoshell-hos-${{ inputs.profile }}.hap
path: target/openharmony/aarch64-unknown-linux-ohos/${{ inputs.profile }}/entry/build/harmonyos/outputs/default/servoshell-default-unsigned.hap
test-harmonyos-aarch64:
name: Test HarmonyOS aarch64
# Don't block servos Merge queue on this job failing.
# Since we just added this, there might be some hidden issues,
# so in the beginning we will just do a best effort approach but ignore errors.
continue-on-error: true
runs-on: hos-runner
if: github.repository == 'servo/servo'
needs: build-harmonyos-aarch64
steps:
- uses: actions/download-artifact@v4
with:
# Name of the artifact to download.
# If unspecified, all artifacts for the run are downloaded.
name: servoshell-hos-${{ inputs.profile }}.hap
- name: Test hdc device
# First we ensure a device is actually connected and working.
run: hdc list targets && hdc shell echo hello world
- name: Sign the hap
run: |
ls -la
/usr/bin/sign-hos.sh servoshell-default-unsigned.hap servoshell-hos-signed.hap
- name: Install
run: |
# Uninstall first. hdc is not very reliable in terms of exiting with an error, so we uninstall first
# to make sure we don't use a previous version if installation failed for some reason.
hdc uninstall org.servo.servo
hdc install -r servoshell-hos-signed.hap
- name: Test loading servo.org
env:
TRACE_BUFFER_SZ_KB: "524288" # 512 MB
run: |
mkdir test_output
hdc shell aa force-stop org.servo.servo
# Hitrace allows us to save application and system traces, which is useful to analyze performance.
# The main reason however, is that we can use the application traces to determine if servo
# successfully reaches certain locations in the code, in particular if a page is successfully loaded.
hdc shell hitrace -b "${TRACE_BUFFER_SZ_KB}" app graphic ohos freq idle memory --trace_begin
# We start servo, tell it to load a website (servo.org). JIT is not allowed on HarmonyOS 5.
hdc shell aa start -a EntryAbility -b org.servo.servo -U https://servo.org --ps=--pref js_disable_jit=true
servo_pid=$(hdc shell pidof org.servo.servo)
# We don't really know how long servo needs to load a webpage, so we just wait 10s.
sleep 10
# We dump the trace in ftrace format to disk
hdc shell hitrace -b "${TRACE_BUFFER_SZ_KB}" --trace_finish -o /data/local/tmp/ohtrace.txt
hdc shell snapshot_display -f /data/local/tmp/servo.jpeg
hdc file recv /data/local/tmp/servo.jpeg test_output/servo_hos_screenshot.jpeg
hdc file recv /data/local/tmp/ohtrace.txt test_output/servo.ftrace
# To limit the logsize we only save logs from servo.
hdc shell hilog --exit -D 0xE0C3 > test_output/servo.log
# todo: Also benchmark some other websites....
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
path: test_output
name: hos-${{ inputs.profile }}-test-output
- name: Check success
run: |
# would be empty if servo crashed.
servo_pid=$(hdc shell pidof org.servo.servo)
[[ $servo_pid =~ ^[0-9]+$ ]] || { echo "It looks like servo crashed!" ; exit 1; }
# If the grep fails, then the trace output for the "page loaded" prompt is missing
grep 'org\.servo\.servo-.* tracing_mark_write.*PageLoadEndedPrompt' test_output/servo.ftrace
bench-harmonyos-aarch64:
name: Benching HarmonyOS aarch64
continue-on-error: true
runs-on: hos-runner
needs: test-harmonyos-aarch64
if: github.repository == 'servo/servo'
steps:
- uses: actions/download-artifact@v4
with:
# Name of the artifact to download.
# If unspecified, all artifacts for the run are downloaded.
name: servoshell-hos-${{ inputs.profile }}.hap
- name: Test hdc device
# First we ensure a device is actually connected and working.
run: hdc list targets && hdc shell echo hello world
- name: Sign the hap
run: |
ls -la
/usr/bin/sign-hos.sh servoshell-default-unsigned.hap servoshell-hos-signed.hap
- name: Install
run: |
# Uninstall first. hdc is not very reliable in terms of exiting with an error, so we uninstall first
# to make sure we don't use a previous version if installation failed for some reason.
hdc uninstall org.servo.servo
hdc install -r servoshell-hos-signed.hap
- uses: actions/checkout@v4
if: github.event_name != 'pull_request_target'
with:
fetch-depth: 0
# This is necessary to checkout the pull request if this run was triggered via a
# `pull_request_target` event.
- uses: actions/checkout@v4
if: github.event_name == 'pull_request_target'
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Setup Python
uses: ./.github/actions/setup-python
- name: Getting hitrace-bench version
run: echo "INSTALLED_HITRACE_BENCH_VERSION=$(hitrace-bench --version | awk '{print $2}')" >> $GITHUB_ENV
- name: Install hitrace-bench
run: cargo install --locked hitrace-bench --version $HITRACE_BENCH_VERSION
if: ${{ env.INSTALLED_HITRACE_BENCH_VERSION != env.HITRACE_BENCH_VERSION }}
- name: "Run benchmark"
run: hitrace-bench -r support/hitrace-bencher/runs.json --bencher -p ${{ inputs.profile }}
continue-on-error: true
- name: Run speedometer
id: BencherRun
run: ./mach test-speedometer-ohos --bmf-output speedometer.json --profile ${{ inputs.profile }}
continue-on-error: true
- name: Create empty speedometer.json if failed
run: touch speedometer.json
if: ${{ steps.BencherRun.outcome == 'failure' }}
- name: Getting model name
# awk is used to remove trailing spaces
run: |
echo "MODEL_NAME=$(hdc shell param get const.product.name | awk '{$1=$1;print}' )" >> $GITHUB_ENV
- name: Combining bencher files
run: jq --compact-output --slurp add speedometer.json bench.json > combined-bencher.json
- uses: bencherdev/bencher@main
# set options
- name: Set bencher opts for PRs (label try run)
if: github.event_name == 'pull_request_target'
run: |
echo "RUN_BENCHER_OPTIONS=--branch ${{ github.event.number }}/PR \
--start-point ${{ github.base_ref }} \
--start-point-hash ${{ github.event.pull_request.base.sha }} \
--start-point-reset \
--start-point-clone-thresholds" >> "$GITHUB_ENV"
- name: Set bencher opts for main
if: ${{ github.event_name == 'push' && github.ref_name == 'main' }}
run: |
echo "RUN_BENCHER_OPTIONS=--branch main" >> "$GITHUB_ENV"
- name: Set bencher opts for try branch
if: ${{ github.event_name == 'push' && github.ref_name == 'try' }}
run: |
git remote add upstream https://github.com/servo/servo
git fetch upstream main
echo "RUN_BENCHER_OPTIONS=--branch try \
--hash $(git rev-parse HEAD~1) \
--start-point main \
--start-point-hash $(git merge-base upstream/main HEAD) \
--start-point-clone-thresholds \
--start-point-reset" >> "$GITHUB_ENV"
- name: Uploading to bencher.dev
# Note: That e.g. `--start-point` is ignored if it is an empty string,
# which should be the case on e.g. normal push workflows on main.
run: |
bencher run --adapter json \
--file combined-bencher.json \
--project '${{ env.BENCHER_PROJECT }}' \
--token '${{ secrets.BENCHER_API_TOKEN }}' \
--github-actions '${{ secrets.GITHUB_TOKEN }}' \
--testbed="$MODEL_NAME" \
$RUN_BENCHER_OPTIONS
- name: Success
if: ${{ !contains(steps.*.outcome, 'failure') && !contains(steps.*.outcome, 'cancelled') }}
run: exit 0
- name: Failure
if: contains(steps.*.outcome, 'failure') || contains(steps.*.outcome, 'cancelled')
run: exit 1