Skip to content

Callback Support

The tuxsuite cli provides a way to push notification to a given http(s) based URL at the end of the build/oebuild/test run. The URL should be passed by the optional argument --callback as shown below:

tuxsuite build \
--git-repo https://github.com/torvalds/linux.git \
--git-ref master \
--target-arch arm \
--toolchain clang-16 \
--kconfig tinyconfig \
--callback https://tuxapi.tuxsuite.com/v1/test_callback

NOTE: The above callback URL is shown as an example and it does not exist.

In order to get a push notification to a given http(s) based URL at the end of a plan submission, use the --plan-callback optional argument as shown below:

tuxsuite plan submit \
--plan-callback https://tuxapi.tuxsuite.com/v1/test_plan_callback \
plan-v1.yaml

NOTE: The above plan callback URL is shown as an example and it does not exist.

To supply extra header to be included when calling the plan callback URL use the --plan-callback-header option, one or more times as shown below:

tuxsuite plan submit \
--plan-callback https://tuxapi.tuxsuite.com/v1/test_plan_callback \
--plan-callback-header "X-First-Name: Senthil" \
--plan-callback-header "X-Last-Name: Kumaran" \
plan-v1.yaml

Security

The JSON data POSTed by Tux backend comes with a security feature which allows the user to verify that the callback notification comes from the Tux backend and not anywhere else. There is a signature which is sent as part of the POST request header called x-tux-payload-signature. This signature is base64 encoded and can be used to verify the authenticity of the sender of the notification.

Following is the verification code in Python:

import base64


from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes, serialization


def verify(public_key: str, signature: str, payload: str):
   """Function to illustrate the verification of the signature."""
   signature = base64.urlsafe_b64decode(signature)
   key = serialization.load_ssh_public_key(public_key.encode("ascii"))
       try:
           key.verify(
               signature,
               payload.encode("utf-8"),
               ec.ECDSA(hashes.SHA256()),
           )
           return True
       except InvalidSignature:
           return False
  • public_key: The public key should be cached in the user's server that accepts the push notification. The public key for a specific Tux group (tuxsuite in this case) can be obtained as follows:
curl https://tuxapi.tuxsuite.com/v1/groups/tuxsuite/projects/demo/keys -o keys.json
  • signature: This is the signature that is sent with the x-tux-payload-signature header in the request.

  • payload: The JSON payload is sent as part of the request. The value of kind in the JSON, will be one of build/oebuild/test/plan. Following is a sample JSON payload, for illustration:

Click to see payload sample for a build
{
    "kind": "build",
    "status": {
        "auto_retry": true,
        "build_name": "",
        "build_status": "pass",
        "callback": "https://tuxapi.tuxsuite.com/v1/test_callback",
        "client_token": "82ce12c7-c41a-4ebf-9771-198b8e9e3aa2",
        "download_url": "https://storage.tuxsuite.com/public/demo/demo/builds/2ZITcwA6wxeKxh9cZA5HBJ6FkSj/",
        "duration": 258,
        "environment": {},
        "errors_count": 0,
        "finished_time": "2023-12-09T08:08:24.822016",
        "git_describe": "v6.7-rc4-111-g5e3f5b81de80",
        "git_ref": "master",
        "git_repo": "https://gitlab.com/Linaro/lkft/mirrors/stable/linux-stable-rc",
        "git_sha": "5e3f5b81de80c98338bcb47c233aebefee5a4801",
        "git_short_log": "5e3f5b81de80 (\"Merge tag 'net-6.7-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net\")",
        "image_sha": "",
        "is_canceling": false,
        "is_public": true,
        "kconfig": [
            "tinyconfig"
        ],
        "kernel_image": "",
        "kernel_image_name": "Image.gz",
        "kernel_patch_file": "",
        "kernel_version": "6.7.0-rc4",
        "make_variables": {
            "LLVM": "1",
            "LLVM_IAS": "1"
        },
        "modules": false,
        "no_cache": false,
        "plan": null,
        "project": "demo/demo",
        "provisioning_time": "2023-12-09T07:57:56.699401",
        "result": "pass",
        "retry": 0,
        "retry_message": "",
        "running_time": "2023-12-09T08:03:50.889831",
        "sccache_hits": 643,
        "sccache_misses": 2,
        "setup_duration": 132,
        "state": "finished",
        "status_message": "build completed",
        "target_arch": "arm64",
        "targets": [],
        "token_name": "demo-tuxsuite",
        "toolchain": "clang-17",
        "tuxbuild_status": "complete",
        "tuxmake_metadata": {
            "compiler": {
                "name": "clang",
                "version": "17.0.6",
                "version_full": "Debian clang version 17.0.6 (++20231128093145+6009708b4367-1~exp1~20231128093253.72)"
            },
            "results": {
                "artifacts": {
                    "config": [
                        "config"
                    ],
                    "debugkernel": [
                        "vmlinux.xz",
                        "System.map"
                    ],
                    "default": [],
                    "dtbs": [
                        "dtbs.tar.xz"
                    ],
                    "dtbs-legacy": [
                        "dtbs.tar.xz"
                    ],
                    "headers": [
                        "headers.tar.xz"
                    ],
                    "kernel": [
                        "Image.gz"
                    ],
                    "log": [
                        "build.log",
                        "build-debug.log"
                    ],
                    "modules": [],
                    "xipkernel": []
                },
                "duration": {
                    "build": 53.78269052505493,
                    "cleanup": 0.34334325790405273,
                    "copy": 0.021654129028320312,
                    "metadata": 0.8076236248016357,
                    "prepare": 142.58426547050476,
                    "validate": 0.00023031234741210938
                },
                "errors": 0,
                "status": "PASS",
                "targets": {
                    "config": {
                        "duration": 9.226672887802124,
                        "status": "PASS"
                    },
                    "debugkernel": {
                        "duration": 1.036712408065796,
                        "status": "PASS"
                    },
                    "default": {
                        "duration": 30.07289409637451,
                        "status": "PASS"
                    },
                    "dtbs": {
                        "duration": 3.9019832611083984,
                        "status": "PASS"
                    },
                    "dtbs-legacy": {
                        "duration": 0.5993697643280029,
                        "status": "SKIP"
                    },
                    "headers": {
                        "duration": 5.118199825286865,
                        "status": "PASS"
                    },
                    "kernel": {
                        "duration": 2.5232584476470947,
                        "status": "PASS"
                    },
                    "modules": {
                        "duration": 0.3326840400695801,
                        "status": "SKIP"
                    },
                    "xipkernel": {
                        "duration": 0.3573451042175293,
                        "status": "SKIP"
                    }
                },
                "warnings": 0
            },
            "runtime": {
                "image_digest": "855116176053.dkr.ecr.us-east-1.amazonaws.com/tuxmake/arm64_clang-17@sha256:2de64794a3c18b331f17ee0ce9a1948450096784ec7db2e5deae089072ccbb73",
                "image_name": "855116176053.dkr.ecr.us-east-1.amazonaws.com/tuxmake/arm64_clang-17",
                "version": "podman version 4.6.2"
            },
            "tools": {
                "ar": "GNU ar (GNU Binutils for Debian) 2.35.2",
                "as": "GNU assembler (GNU Binutils for Debian) 2.35.2",
                "bc": "bc 1.07.1",
                "bison": "bison (GNU Bison) 3.7.5",
                "ccache": "ccache version 4.2",
                "clang": "Debian clang version 17.0.6 (++20231128093145+6009708b4367-1~exp1~20231128093253.72)",
                "depmod": "kmod version 28",
                "fdformat": "fdformat from util-linux 2.36.1",
                "flex": "flex 2.6.4",
                "gcc": "gcc (Debian 10.2.1-6) 10.2.1 20210110",
                "ld": "GNU ld (GNU Binutils for Debian) 2.35.2",
                "lld": "Debian LLD 17.0.6 (compatible with GNU linkers)",
                "make": "GNU Make 4.3",
                "openssl": "OpenSSL 1.1.1w  11 Sep 2023",
                "pahole": "v1.25",
                "ps": "ps from procps-ng 3.3.17",
                "sccache": "sccache 0.2.9"
            },
            "tuxmake": {
                "version": "1.20.0"
            }
        },
        "uid": "2ZITcwA6wxeKxh9cZA5HBJ6FkSj",
        "user": "demo.user@linaro.org",
        "user_agent": "tuxsuite/1.33.0",
        "waited_by": [],
        "warnings_count": 0
    }
}
Click to see payload sample for a test
{
    "kind": "test",
    "status": {
        "ap_romfw": null,
        "bios": null,
        "bl1": null,
        "boot_args": null,
        "callback": "https://tuxapi.tuxsuite.com/v1/test_callback",
        "device": "qemu-arm64",
        "download_url": "https://storage.tuxsuite.com/public/tuxsuite/demo/tests/2MBYa8FhoBHkRCX2BMMPusjuClf/",
        "dtb": null,
        "duration": 117,
        "finished_time": "2023-02-24T12:44:23.178581",
        "fip": null,
        "is_canceling": false,
        "is_public": true,
        "kernel": "https://storage.tuxsuite.com/public/linaro/lkft/builds/2M0PXsQDVWO3DwIKTIlwtDELTpb/Image.gz",
        "mcp_fw": null,
        "mcp_romfw": null,
        "modules": "https://storage.tuxsuite.com/public/linaro/lkft/builds/2M0PXsQDVWO3DwIKTIlwtDELTpb/modules.tar.xz",
        "parameters": {
            "SHARD_INDEX": "4",
            "SHARD_NUMBER": "10",
            "SKIPFILE": "skipfile-lkft.yaml"
        },
        "plan": null,
        "project": "tuxsuite/demo",
        "provisioning_time": "2023-02-24T12:41:42.541788",
        "result": "pass",
        "results": {
            "boot": "pass"
        },
        "retries": 0,
        "retries_messages": [],
        "rootfs": "https://storage.tuxsuite.com/public/linaro/lkft/oebuilds/2LjyTGHSPqxUqtyCl1xI7SCrbWp/images/juno/lkft-tux-image-juno-20230214185536.rootfs.ext4.gz",
        "running_time": "2023-02-24T12:42:27.314447",
        "scp_fw": null,
        "scp_romfw": null,
        "state": "finished",
        "tests": [
            "boot"
        ],
        "timeouts": {},
        "token_name": "demo-tuxsuite",
        "uefi": null,
        "uid": "2MBYa8FhoBHkRCX2BMMPusjuClf",
        "user": "demo.user@linaro.org",
        "user_agent": "tuxsuite/1.9.0",
        "waiting_for": null
    }
}
Click to see payload sample for a oebuild
{
    "kind": "oebuild",
    "status": {
        "artifacts": [],
        "bblayers_conf": [],
        "callback": "https://tuxapi.tuxsuite.com/v1/test_callback",
        "container": "ubuntu-20.04",
        "distro": "oniro-linux",
        "download_url": "https://storage.tuxsuite.com/public/demo/demo/oebuilds/2ZITcWtwDj3povtoSM0c5sk30FZ/",
        "duration": 127,
        "environment": {
            "TEMPLATECONF": "../oniro/flavours/linux"
        },
        "envsetup": "oe-core/oe-init-build-env",
        "errors_count": 0,
        "extraconfigs": [],
        "finished_time": "2023-12-09T08:02:19.569984",
        "is_canceling": false,
        "is_public": true,
        "kas_override": null,
        "local_conf": [],
        "machine": "qemux86-64",
        "manifest_file": null,
        "name": "",
        "no_cache": false,
        "pinned_manifest": null,
        "plan": null,
        "project": "demo/demo",
        "provisioning_time": "2023-12-09T07:57:53.449324",
        "result": "pass",
        "running_time": "2023-12-09T08:00:15.165104",
        "setup_duration": 103,
        "sources": {
            "repo": {
                "branch": "kirkstone",
                "manifest": "default.xml",
                "url": "https://gitlab.eclipse.org/eclipse/oniro-core/oniro"
            }
        },
        "state": "finished",
        "status_message": "",
        "targets": [
            "intltool-native"
        ],
        "token_name": "demo-tuxsuite",
        "uid": "2ZITcWtwDj3povtoSM0c5sk30FZ",
        "user": "demo.user@linaro.org",
        "user_agent": "tuxsuite/1.33.0",
        "waited_by": [],
        "warnings_count": 0
    }
}
Click to see payload sample for a plan
{
    "kind": "plan",
    "status": {
        "description": "Plan Callback Tester",
        "is_public": true,
        "name": "Plan Callback Tester",
        "plan_callback": "https://tuxapi.tuxsuite.com/v1/test_callback",
        "project": "tuxsuite/demo",
        "provisioning_time": "2023-12-09T07:48:26.003703",
        "state": "finished",
        "token_name": "demo-tuxsuite",
        "uid": "2ZISTKlXYwYx1k5K4p8HIEKu7kn",
        "user": "demo.user@linaro.org",
        "user_agent": "tuxsuite/1.33.0"
    }
}

NOTE: The Tux backends use ECDSA based cryptogrphic key pairs in order to create the signature.