diff --git a/.github/workflows/itf-qnx.yml b/.github/workflows/itf-qnx.yml new file mode 100644 index 0000000..ee567c3 --- /dev/null +++ b/.github/workflows/itf-qnx.yml @@ -0,0 +1,58 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +name: ITF QNX QEMU Tests +on: + pull_request: + types: [opened, reopened, synchronize] +jobs: + itf-qnx-qemu-tests-build-all: + runs-on: ubuntu-latest + environment: workflow-approval + permissions: + contents: read + pull-requests: read + steps: + - name: Checkout repository + uses: actions/checkout@v4.2.2 + - name: Setup Bazel + uses: bazel-contrib/setup-bazel@0.14.0 + - name: Setup QNX License + env: + SCORE_QNX_LICENSE: ${{ secrets.SCORE_QNX_LICENSE }} + run: | + mkdir -p /opt/score_qnx/license + echo "${SCORE_QNX_LICENSE}" | base64 --decode > /opt/score_qnx/license/licenses + - name: Install qemu + run: | + sudo apt-get update + sudo apt-get install -y qemu-system + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + - name: Allow unprivileged user namespaces + run: | + sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0 + - name: Build and test + env: + SCORE_QNX_USER: ${{ secrets.SCORE_QNX_USER }} + SCORE_QNX_PASSWORD: ${{ secrets.SCORE_QNX_PASSWORD }} + run: | + bazel test --config=qemu-integration //test:qnx_qemu_tests \ + --credential_helper=*.qnx.com=${{ github.workspace }}/tools/qnx_credential_helper.py + - name: Cleanup QNX License + if: always() + run: | + rm -rf /opt/score_qnx + rm -rf "${HOME}/.cache/bazel" diff --git a/test/BUILD b/test/BUILD index 9baf36e..ca61476 100644 --- a/test/BUILD +++ b/test/BUILD @@ -119,7 +119,6 @@ py_itf_test( "//score/itf/plugins:dlt_plugin", ], tags = [ - "local", "manual", ], ) @@ -141,7 +140,6 @@ py_itf_test( "//score/itf/plugins:qemu_plugin", ], tags = [ - "local", "manual", ], ) @@ -164,11 +162,23 @@ py_itf_test( "//score/itf/plugins:dlt_plugin", ], tags = [ - "local", "manual", ], ) +test_suite( + name = "qnx_qemu_tests", + tags = [ + "manual", + ], + tests = [ + ":test_qemu_bridge_network", + ":test_qemu_bridge_network_no_dlt", + ":test_qemu_port_forwarding", + ":test_ssh_configurable", + ], +) + py_itf_test( name = "test_ping", srcs = [ diff --git a/tools/qnx_credential_helper.py b/tools/qnx_credential_helper.py new file mode 100755 index 0000000..4f2ff54 --- /dev/null +++ b/tools/qnx_credential_helper.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +# ******************************************************************************* +# Copyright (c) 2026 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +import http.cookiejar +import json +import netrc +import os +import sys +import urllib.parse +import urllib.request + + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + + +if __name__ == "__main__": + data = json.load(sys.stdin) + + if "qnx.com" not in data["uri"]: + eprint("Unsupported domain") + sys.exit(1) + + if "SCORE_QNX_USER" in os.environ and "SCORE_QNX_PASSWORD" in os.environ: + login = os.environ["SCORE_QNX_USER"] + password = os.environ["SCORE_QNX_PASSWORD"] + else: + try: + nrc = netrc.netrc() + auth = nrc.authenticators("qnx.com") + if auth: + login, _, password = auth + else: + raise Exception("No credential found for QNX") + except Exception as excp: + eprint(excp) + eprint("Failed getting credentials from .netrc") + sys.exit(1) + + data = urllib.parse.urlencode({"userlogin": login, "password": password, "UseCookie": "1"}) + data = data.encode("ascii") + + cookie_jar = http.cookiejar.CookieJar() + cookie_processor = urllib.request.HTTPCookieProcessor(cookie_jar) + opener = urllib.request.build_opener(cookie_processor) + urllib.request.install_opener(opener) + + r = urllib.request.urlopen("https://www.qnx.com/account/login.html", data) + if r.status != 200: + eprint("Failed to login to QNX") + sys.exit(1) + + cookies = {c.name: c.value for c in list(cookie_jar)} + if not "myQNX" in cookies: + eprint("Failed to get myQNX cookie from login page") + sys.exit(1) + + myQNX = cookies["myQNX"] + print( + json.dumps( + { + "headers": { + "Cookie": [f"myQNX={myQNX}"], + } + } + ) + )