You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[C] e2e: mqttv5 custom topics, and a ci-c-e2e-mqttv5 workflow - #413
Adds e2e tests for the mqttv5 custom topic client (#409), and a ci-c-e2e-mqttv5 workflow to run mqttv5 e2e suites. Further mqttv5 clients can be added to it as separate jobs.
Test (c/tests/e2e/tests/e2e_mqttv5_custom_topic_test.c)
The device provisions through DPS (e2e_device.c) onto an mqttv5 hub with the custom topic templates e2e/{deviceId}/# and e2e/shared/#. Cases:
Baseline: mqttv5 telemetry reaches the events endpoint. This separates environment problems from custom-topic problems.
QoS 1 to e2e/{deviceId}/telemetry is acknowledged and reaches the events endpoint.
QoS 0 to e2e/shared/alerts reaches the events endpoint.
e2e-unlisted/telemetry (no template) is refused and not routed.
e2e/not-{deviceId}/telemetry (another device's id) is refused and not routed.
The session keeps publishing after the refusals.
It is built only with AZ_IOT_BUILD_E2E_MQTTV5, so ci-c-e2e (ctest -R e2e) does not pick it up.
Issues a per-run device from the shared X.509 group CA with e2e-shared-device.ps1 -Prefix E2E_MQTTV5_SHARED.
Reads the events endpoint through consumer group e2e-<run % 10>.
Skips when E2E_MQTTV5_SHARED_ID_SCOPE is unset, and for pull requests from forks.
Triggers: pull requests touching mqttv5 or core device code, adapters, the e2e harness or these workflows; nightly; manual.
c/eng/e2e-shared-device.ps1
New -Prefix E2E_MQTTV5_SHARED reads that environment's variables.
E2E_MQTTV5_SHARED_DPS_HOST maps to IOT_DPS_GLOBAL_ENDPOINT.
The default and -Csr outputs are unchanged.
Validation
Test, run locally in DPS mode against the shared mqttv5 environment (Linux, Paho):
cases 1, 4, 5 and 6 pass;
cases 2 and 3 fail: the hub acknowledges the custom-topic publishes, but they never reach the events endpoint (90 s wait), while the baseline telemetry does. This was reproduced over several runs and also with the az_mqtt adapter, which shows the refusals as PUBACK 0x87. It is a hub-side routing issue, so this workflow's job will fail on those two cases until it is fixed.
The workflow's Run step was run locally in PowerShell with an equivalent test config.
e2e-shared-device.ps1 was tested with a local CA in every mode: default, -Prefix E2E_MQTTV5_SHARED, -Csr, missing variables, and the iothubowner policy rejected. The issued leaf verifies against the CA.
actionlint 1.7.12 and zizmor 1.30.1: clean. The reusable-workflow call keeps ./ with an inline zizmor ignore, because actionlint 1.7.12 rejects the $/ form.
Repository checks and clang-format 18: clean.
Not run in GitHub Actions yet: the OIDC login for pull requests in the namespace job, and device issuance from the real group CA secret.
- e2e_mqttv5_custom_topic_test.c: on an mqttv5 hub with the templates
e2e/{deviceId}/# and e2e/shared/#, QoS 1 and QoS 0 publishes reach the
events endpoint; a topic no template allows and another device's id are
refused without a disconnect, and the session keeps publishing.
Telemetry runs first as a baseline. Built with AZ_IOT_BUILD_E2E_MQTTV5.
- ci-c-e2e-mqttv5.yml: runs mqttv5 suites on the shared mqttv5 environment,
one job per client, after the ADR namespace job. Skips when
E2E_MQTTV5_SHARED_ID_SCOPE is unset and for pull requests from forks.
- e2e-shared-device.ps1: -Prefix E2E_MQTTV5_SHARED reads that environment's
variables, and E2E_MQTTV5_SHARED_DPS_HOST sets the DPS endpoint. Default
unchanged.
…kip switch
- Publish records live in the fixture, so a PUBACK after a timed-out wait
cannot complete a freed stack record.
- AZ_IOT_E2E_SKIP_CUSTOM_TOPIC_ROUTING turns the routed checks into skips
when nothing arrives; ci-c-e2e-mqttv5 sets it while the hub does not
deliver custom topic messages to the events endpoint.
This assertion accepts every failure, so a transient disconnect, timeout, or quota error would make the test pass without proving that the unlisted topic was refused. The two documented outcomes for this scenario are AZ_IOT_ERR_PUBLISH_REFUSED when the adapter preserves PUBACK 0x87 and AZ_IOT_ERR_MQTT when it does not; restrict the assertion to those values.
This issue also appears on line 340 of the same file.
Re: refusal cases accepting unrelated failures: fixed in c672073. They now pass only on AZ_IOT_ERR_PUBLISH_REFUSED (PUBACK 0x87) or AZ_IOT_ERR_MQTT (adapter without reason codes); a timeout, disconnect or quota error fails them.
Exclude Dependabot PRs from secret-dependent workflow jobs
.github/workflows/ci-c-e2e-mqttv5.yml:54
Dependabot pull requests are treated like fork-originated workflows for secret access even when head.repo.full_name equals this repository. This repository schedules weekly GitHub Actions updates, so an update to this workflow can satisfy this condition while AZURE_CLIENT_ID, the CA, and the connection-string secrets are empty, producing a guaranteed failing e2e run. Exclude dependabot[bot] from the PR path rather than starting the secret-dependent jobs.
Use the full routing window for negative delivery tests
The negative cases declare a message “not routed” after only 30 seconds, while the same endpoint is allowed 90 seconds to deliver routed messages. A forbidden message delivered after 30 seconds would therefore make these tests pass incorrectly. Observe non-delivery for the same routing window unless the service has a documented shorter upper bound.
The direct-connect claim is not supported by this fixture: e2e_device_connect() leaves connection_profile at its MQTT v3 default in direct-hub mode, so the profile check below rejects it before the custom-topic client initializes. Remove this claim, or add a way for the shared fixture to declare MQTT v5 for direct connections.
…on-delivery
- ci-c-e2e-mqttv5 skips pull requests from Dependabot, which get no secrets.
- Refused publishes are watched for the same 90 s as routed ones.
- The test header no longer claims direct-hub mode; e2e_device connects
directly as mqttv3.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The workflow depends on unverified production OIDC and CA-backed provisioning paths, while routing assertions remain conditionally skipped.
0 open findings
🧠 Review effort: Balanced
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds e2e tests for the mqttv5 custom topic client (#409), and a
ci-c-e2e-mqttv5workflow to run mqttv5 e2e suites. Further mqttv5 clients can be added to it as separate jobs.Test (
c/tests/e2e/tests/e2e_mqttv5_custom_topic_test.c)The device provisions through DPS (
e2e_device.c) onto an mqttv5 hub with the custom topic templatese2e/{deviceId}/#ande2e/shared/#. Cases:e2e/{deviceId}/telemetryis acknowledged and reaches the events endpoint.e2e/shared/alertsreaches the events endpoint.e2e-unlisted/telemetry(no template) is refused and not routed.e2e/not-{deviceId}/telemetry(another device's id) is refused and not routed.It is built only with
AZ_IOT_BUILD_E2E_MQTTV5, soci-c-e2e(ctest -R e2e) does not pick it up.Workflow (
.github/workflows/ci-c-e2e-mqttv5.yml)adr-namespacecallsci-c-e2e-mqttv5-adr-namespace.ymlfirst.custom-topics / linux:e2e-shared-device.ps1 -Prefix E2E_MQTTV5_SHARED.e2e-<run % 10>.E2E_MQTTV5_SHARED_ID_SCOPEis unset, and for pull requests from forks.c/eng/e2e-shared-device.ps1-Prefix E2E_MQTTV5_SHAREDreads that environment's variables.E2E_MQTTV5_SHARED_DPS_HOSTmaps toIOT_DPS_GLOBAL_ENDPOINT.-Csroutputs are unchanged.Validation
0x87. It is a hub-side routing issue, so this workflow's job will fail on those two cases until it is fixed.e2e-shared-device.ps1was tested with a local CA in every mode: default,-Prefix E2E_MQTTV5_SHARED,-Csr, missing variables, and the iothubowner policy rejected. The issued leaf verifies against the CA../with an inline zizmor ignore, because actionlint 1.7.12 rejects the$/form.