diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f5a01fcc..5bd5268a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: permissions: statuses: write buildTestAyaEbpf: - uses: melodium-tech/github-actions/.github/workflows/melodium-local-distrib.yml@v0.9.1 + uses: melodium-tech/github-actions/.github/workflows/melodium-ubuntu.yml@v0.9.1 with: command: | run .melodium-ci/Compo.toml buildTestAyaEbpf --repository_clone_url='"${{ github.repositoryUrl }}"' --repository_clone_ref='"${{ github.ref_name }}"' --github_contexts='$''{{{{ { "github": { "api_url": ${{ toJSON(github.api_url) }}, "repository": ${{ toJSON(github.repository) }}, "sha": ${{ toJSON(github.sha) }} }, "secrets": { "GITHUB_TOKEN": "'"$GITHUB_TOKEN"'" } } }}}}' diff --git a/.melodium-ci/Compo.toml b/.melodium-ci/Compo.toml index c8203d24..3bfdb4e9 100644 --- a/.melodium-ci/Compo.toml +++ b/.melodium-ci/Compo.toml @@ -16,5 +16,5 @@ work = "^0.9.1" [entrypoints] buildTestAya = "ci/build_test_aya::buildTestAya" -buildTestAyaEbpf = "ci::buildTestAyaEbpfEntrypoint" +buildTestAyaEbpf = "ci/build_test_aya_ebpf::buildTestAyaEbpfEntrypoint" diff --git a/.melodium-ci/build_test_aya.mel b/.melodium-ci/build_test_aya.mel index 789ad464..3dab93e4 100644 --- a/.melodium-ci/build_test_aya.mel +++ b/.melodium-ci/build_test_aya.mel @@ -1,17 +1,13 @@ use cicd/logging::manageLogs use cicd/naive::localStep use cicd/services/github::prepareContexts -use cicd/services/github::postGithubStateContext -use cicd/services/github::|pending -use cicd/services/github::|success -use cicd/services/github::|error -use cicd/services/github::|failure use javascript::JavaScriptEngine use log/logger::Logger use process/command::|command use root/prepare::checkout use root/prepare::setupToolchain use root/prepare::prepareRust +use root/report::reportState use std/data/string_map::StringMap use std/data/string_map::|entry use std/data/string_map::|map @@ -100,20 +96,21 @@ treatment buildTestAyaForArch[logger: Logger, github_contexts: JavaScriptEngine, run.finished -> Self.finished - pendingState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |pending(), name = rust_target, description = "Build and Test Aya on arch", log_response = true) - successState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |success(), name = rust_target, description = "Build and Test Aya on arch", log_response = true) - errorState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |error(), name = rust_target, description = "Build and Test Aya on arch", log_response = true) - failureState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |failure(), name = rust_target, description = "Build and Test Aya on arch", log_response = true) + reportState[logger=logger, github_contexts=github_contexts]( + name=rust_target, + description="Build and Test Aya on arch", + log_response=true + ) - doRun.passed --> pendingState.trigger - run.success ---> successState.trigger - run.error -----> errorState.trigger + doRun.passed --> reportState.pending + run.success ---> reportState.success + run.error -----> reportState.error uncheckSuccess: uncheck() oneFailure: one() realFailure: waitBlock() run.success -> uncheckSuccess.value,uncheck -> oneFailure.a - run.failed ----------------------------------> oneFailure.b,value -> realFailure.a,awaited -> failureState.trigger + run.failed ----------------------------------> oneFailure.b,value -> realFailure.a,awaited -> reportState.failure doRun.passed ------------------------------------------------------> realFailure.b } diff --git a/.melodium-ci/build_test_aya_ebpf.mel b/.melodium-ci/build_test_aya_ebpf.mel new file mode 100644 index 00000000..9b000496 --- /dev/null +++ b/.melodium-ci/build_test_aya_ebpf.mel @@ -0,0 +1,156 @@ +use cicd/logging::manageLogs +use cicd/naive::localStep +use cicd/services/github::prepareContexts +use javascript::JavaScriptEngine +use log/logger::Logger +use process/command::|command +use process/command::|raw_commands +use root/prepare::checkout +use root/report::reportState +use std/data/string_map::StringMap +use std/data/string_map::|entry +use std/data/string_map::|map +use std/engine/util::startup +use std/flow::one +use std/flow::passBlock +use std/flow::uncheck +use std/flow::waitBlock +use std/flow::trigger +use std/ops/option::|wrap + +treatment buildTestAyaEbpf[logger: Logger, github_contexts: JavaScriptEngine](repository_clone_ref: string, repository_clone_url: string) + input trigger: Block + output finished: Block +{ + checkout[logger=logger]( + label="checkout", + repository_clone_url=repository_clone_url, + repository_clone_ref=repository_clone_ref, + clone_directory="/tmp/work" + ) + + rustNightly: localStep[logger=logger]( + name="rustNightly", + commands= [ + |command("rustup", ["toolchain", "install", "nightly", "--component", "rust-src", "--allow-downgrade"]) + ] + ) + + rustStable: localStep[logger=logger]( + name="rustStable", + commands= [ + |command("rustup", ["toolchain", "install", "stable"]) + ] + ) + + cargoHack: localStep[logger=logger]( + name="cargoHack", + commands=|raw_commands([ + ${bash -c "curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash -"}, + "cargo binstall cargo-hack" + ]) + ) + + bpfLinker: localStep[logger=logger]( + name="bpfLinker", + commands= [ + |command("cargo", ["install", "--git", "https://github.com/aya-rs/bpf-linker.git", "bpf-linker", "--features", "llvm-21"]) + ] + ) + + build: localStep[logger=logger]( + name = "build", + commands = [|command("bash", ["-c", ${{{ + set -euo pipefail + + cd /tmp/work + + failures=() + + # NB: this hand-rolled shell script is used instead of a matrix + # because the time spent doing useful work per target is about equal + # to the overhead of setting up the job - so this saves a bunch of + # machine time. + for arch in aarch64 arm loongarch64 mips powerpc64 riscv64 s390x x86_64; do + echo "::group::arch=$arch" + export RUSTFLAGS="--cfg bpf_target_arch=\"$arch\"" + for target in bpfeb-unknown-none bpfel-unknown-none; do + echo "::group::target=$target" + if ! ( + cargo +nightly hack build \ + --release \ + --target "$target" \ + -Z build-std=core \ + --package aya-ebpf \ + --package aya-ebpf-bindings \ + --package aya-log-ebpf \ + --package integration-ebpf \ + --feature-powerset + ); then + failures+=("build: $arch/$target") + fi + echo "::endgroup::" + done + if ! ( + RUSTDOCFLAGS=$RUSTFLAGS cargo +nightly hack test --doc \ + --package aya-ebpf \ + --package aya-ebpf-bindings \ + --package aya-log-ebpf \ + --package integration-ebpf \ + --feature-powerset + ); then + failures+=("doctests: $arch") + fi + echo "::endgroup::" + done + + if ((${#failures[@]})); then + echo "::error::Some builds/tests failed:" + printf ' %s\n' "${failures[@]}" + sleep 1 + exit 1 + fi + }}} + ])], + variables = |wrap( + |map([ + |entry("RUST_BACKTRACE", "full") + ]) + ) + ) + + waitRustStuff: waitBlock() + waitAllReady: waitBlock() + + Self.trigger -> checkout.trigger,success ------------------------------------------------------------------------------------------> waitAllReady.a,awaited -> build.trigger,finished -> Self.finished + Self.trigger -> rustNightly.trigger,success -> rustStable.trigger,success -> cargoHack.trigger,success -> waitRustStuff.a,awaited -> waitAllReady.b + rustStable.success ---------> bpfLinker.trigger,success -> waitRustStuff.b + + + reportState[github_contexts=github_contexts, logger=logger]( + name = "All BPF", + description = "Build & test for all BPF architectures", + log_response = true + ) + Self.trigger --> reportState.pending + build.success -> reportState.success + build.error ---> reportState.error + + uncheckSuccess: uncheck() + oneFailure: one() + build.success -> uncheckSuccess.value,uncheck -> oneFailure.a + build.failed ----------------------------------> oneFailure.b,value -> reportState.failure +} + +treatment buildTestAyaEbpfEntrypoint(const github_contexts: string = "{}", repository_clone_url: string, repository_clone_ref: string) + model logger: Logger() + model github_contexts: JavaScriptEngine() +{ + startup() + prepareContexts[contexts=github_contexts](github_contexts=github_contexts) + manageLogs[logger=logger](output_directory="logs/") + + buildTestAyaEbpf[logger=logger, github_contexts=github_contexts](repository_clone_url=repository_clone_url, repository_clone_ref=repository_clone_ref) + + startup.trigger -> prepareContexts.trigger,ready -> buildTestAyaEbpf.trigger,finished -> manageLogs.stop +} diff --git a/.melodium-ci/report.mel b/.melodium-ci/report.mel new file mode 100644 index 00000000..2a5c769c --- /dev/null +++ b/.melodium-ci/report.mel @@ -0,0 +1,24 @@ +use cicd/services/github::postGithubStateContext +use cicd/services/github::|pending +use cicd/services/github::|success +use cicd/services/github::|error +use cicd/services/github::|failure +use javascript::JavaScriptEngine +use log/logger::Logger + +treatment reportState[logger: Logger, github_contexts: JavaScriptEngine](name: string, description: string, log_response: bool) + input pending: Block + input success: Block + input error: Block + input failure: Block +{ + pendingState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |pending(), name = name, description = description, log_response = log_response) + successState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |success(), name = name, description = description, log_response = log_response) + errorState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |error(), name = name, description = description, log_response = log_response) + failureState: postGithubStateContext[contexts=github_contexts, logger=logger](state = |failure(), name = name, description = description, log_response = log_response) + + Self.pending -> pendingState.trigger + Self.success -> successState.trigger + Self.error ---> errorState.trigger + Self.failure -> failureState.trigger +} \ No newline at end of file