Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/publish-allure-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:
- "meshery-results/**"
- "meshery-server-results/**"
- "mesheryctl-results/**"
- "mesheryctl-bats-results/**"
- "mesheryctl-unit-results/**"
- "remote-provider-results/**"
- "allurerc.mjs"
workflow_dispatch:
Expand Down
54 changes: 43 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,48 @@ include build/Makefile.show-help.mk
# Helpers
# --------------------------------------------------

# Replace the destination ONLY after the source is validated AND the copy has
# fully succeeded. The copy lands in a temporary sibling dir first; the
# destination is removed and swapped in only once that copy completes, so a
# misconfigured source var, a mid-copy I/O error, or a disappearing source can
# never leave the committed results half-deleted. An unset/missing source skips
# entirely and leaves the destination intact. `cp -a "$src/."` copies directory
# contents (and succeeds on an empty source) without relying on glob expansion.
define results-sync
@rm -rf $(2)
@mkdir -p $(2)
@if [ -n "$($(1))" ] && [ -d "$($(1))" ]; then \
echo "Copying results from $($(1)) → $(2)"; \
cp -r "$($(1))"/* $(2)/ ; \
tmp="$(2).tmp.$$$$"; \
rm -rf "$$tmp"; mkdir -p "$$tmp"; \
if cp -a "$($(1))/." "$$tmp/"; then \
rm -rf "$(2)"; mv "$$tmp" "$(2)"; \
else \
echo "Copy failed; destination $(2) left intact"; rm -rf "$$tmp"; exit 1; \
fi; \
else \
echo "$(1) not set or directory does not exist, skipping"; \
echo "$(1) not set or directory does not exist, skipping (destination $(2) left intact)"; \
fi
endef


define results-sync-path
@rm -rf $(2)
@mkdir -p $(2)
@if [ -n "$(1)" ] && [ -d "$(1)" ]; then \
echo "Copying results from $(1) → $(2)"; \
cp -r "$(1)"/* $(2)/ ; \
tmp="$(2).tmp.$$$$"; \
rm -rf "$$tmp"; mkdir -p "$$tmp"; \
if cp -a "$(1)/." "$$tmp/"; then \
rm -rf "$(2)"; mv "$$tmp" "$(2)"; \
else \
echo "Copy failed; destination $(2) left intact"; rm -rf "$$tmp"; exit 1; \
fi; \
else \
echo "$(1) not set or directory does not exist, skipping"; \
echo "$(1) not set or directory does not exist, skipping (destination $(2) left intact)"; \
fi
endef

# --------------------------------------------------
# Targets
# --------------------------------------------------
.PHONY: report-generate meshery-results-sync meshery-server-results-sync mesheryctl-results-sync report-open report
.PHONY: report-generate meshery-results-sync meshery-server-results-sync mesheryctl-results-sync mesheryctl-bats-results-sync mesheryctl-unit-results-sync report-open report

## Sync Meshery Test Results
meshery-results-sync:
Expand All @@ -57,11 +72,23 @@ meshery-server-results-sync:
@echo "Syncing Server Go Unit Test Results..."
$(call results-sync,MESHERY_SERVER_RESULTS_PATH,meshery-server-results)

## Sync mesheryctl Test Results
## Sync mesheryctl Test Results (DEPRECATED - shared by BATS e2e and go unit
## feeders, which clobbered each other since results-sync wipes its target.
## Kept as a back-compat alias; new feeders use the split targets below.)
mesheryctl-results-sync:
@echo "Syncing mesheryctl Test Results..."
$(call results-sync,MESHERYCTL_RESULTS_PATH,mesheryctl-results)

## Sync mesheryctl BATS e2e Test Results
mesheryctl-bats-results-sync:
@echo "Syncing mesheryctl BATS e2e Test Results..."
$(call results-sync,MESHERYCTL_BATS_RESULTS_PATH,mesheryctl-bats-results)

## Sync mesheryctl Go unit Test Results
mesheryctl-unit-results-sync:
@echo "Syncing mesheryctl Go unit Test Results..."
$(call results-sync,MESHERYCTL_UNIT_RESULTS_PATH,mesheryctl-unit-results)
Comment on lines +83 to +90

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed - results-sync (and results-sync-path) now rm -rf the destination only after the source var is confirmed set and present, so a misconfigured or empty path var can no longer wipe committed results before the guard runs. This closes the data-loss window for every sync target, not just the new ones.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is addressed by the macro fix in the same commit: rm -rf/mkdir now sit inside the [ -n ... ] && [ -d ... ] guard, so an unset or missing path var no longer wipes the destination - it logs and leaves the committed results intact. That is the safe-skip behavior already used by the other named sync targets, so I kept it rather than adding a separate exit-1 per target. project-results-sync keeps its own exit-1 because it is the generic entrypoint.


## Generic sync - make project-results-sync RESULTS_DIR=path/to/results PROJECT=myproject
project-results-sync:
@if [ -z "$(RESULTS_DIR)" ] || [ -z "$(PROJECT)" ]; then \
Expand Down Expand Up @@ -91,7 +118,12 @@ report-build:
cp kanvas-results/* allure-results/ || true
cp meshery-results/* allure-results/ || true
cp meshery-server-results/* allure-results/ || true
cp mesheryctl-results/* allure-results/ || true
# NOTE: the legacy mesheryctl-results/ dir is intentionally NOT copied. Its
# results are frozen (both feeders now write to the split dirs below), so
# including it would merge stale pre-split results with current ones. The
# split dirs repopulate on the next CI run of each feeder.
cp mesheryctl-bats-results/* allure-results/ || true
cp mesheryctl-unit-results/* allure-results/ || true
Comment thread
coderabbitai[bot] marked this conversation as resolved.
cp remote-provider-results/* allure-results/ || true
npm run report:generate

Expand Down
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,30 @@ A self-service engineering platform, <a href="https://meshery.io">Meshery</a>, i

Visit https://qa.meshery.io for the Meshery project quality assurance dashboard.

### Published reports

The dashboard is generated by `make report-build` (config in `allurerc.mjs`) and
deployed to GitHub Pages. Each report is a filtered view over one shared pool of
Allure results, selected by test labels:

| Report | Selects results where |
| --- | --- |
| Dashboard | all results (aggregate) |
| Meshery | `project == "Meshery"` |
| Mesheryctl | `project == "mesheryctl"` |
| **Kubernetes Connections** | `epic == "Kubernetes Connections"`; results with no `epic` label also match via the Kubernetes `componentUnderTest` fallback (UI + CLI connection tests, grouped by `client`) |
| Extension: Remote Provider Layer5 Cloud | `project == "Layer5Cloud"` |
| Extension: Kanvas | `project == "Kanvas"` |

The Kubernetes Connections report is a cross-client behavior lens: connection
tests are tagged at their source (UI Playwright specs, CLI converters) with
`epic="Kubernetes Connections"`, `componentUnderTest`, `testId` (`TC-<n>`), and
`client` (`UI`|`CLI`), sourced from the Meshery Test Plan. Tagged tests still
appear in their `project` report; the Connections report is an additional view.
As a fallback, a result that carries no `epic` label at all is included when its
`componentUnderTest` matches Kubernetes, so results predating the `epic`
convention still appear; a result with a *different* `epic` value is not pulled
in by the component fallback.

<p style="clear:both;">&nbsp;</p>

Expand All @@ -98,7 +121,9 @@ The following directories hold generated test data and are safe to exclude (they
| --- | --- |
| `meshery-results/` | Raw Allure results for Meshery integration tests |
| `meshery-server-results/` | Raw Allure results for Meshery Server Go unit tests |
| `mesheryctl-results/` | Raw Allure results for `mesheryctl` tests |
| `mesheryctl-results/` | Raw Allure results for `mesheryctl` tests (deprecated - split into the two dirs below) |
| `mesheryctl-bats-results/` | Raw Allure results for `mesheryctl` BATS e2e tests |
| `mesheryctl-unit-results/` | Raw Allure results for `mesheryctl` Go unit tests |
| `kanvas-results/` | Raw Allure results for Kanvas (extension) |
| `remote-provider-results/` | Raw Allure results for the Remote Provider (extension) |
| `pr-reports/` | Generated per-PR HTML reports (the largest contributor to repo size) |
Expand All @@ -116,6 +141,8 @@ git sparse-checkout set --no-cone \
'!/meshery-results/' \
'!/meshery-server-results/' \
'!/mesheryctl-results/' \
'!/mesheryctl-bats-results/' \
'!/mesheryctl-unit-results/' \
'!/kanvas-results/' \
'!/remote-provider-results/' \
'!/pr-reports/'
Expand All @@ -135,6 +162,7 @@ cd qa
git sparse-checkout set --no-cone \
'/*' \
'!/meshery-results/' '!/meshery-server-results/' '!/mesheryctl-results/' \
'!/mesheryctl-bats-results/' '!/mesheryctl-unit-results/' \
'!/kanvas-results/' '!/remote-provider-results/' '!/pr-reports/'
```

Expand Down
47 changes: 47 additions & 0 deletions allurerc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,33 @@ const PROJECTS = {
const isProject = (labels, projectName) =>
labels.find(({ name, value }) => name === "project" && value === projectName);

// Behavior-scoped report keys. A Connections result is tagged at its source
// (UI Playwright specs and CLI converters) with epic="Kubernetes Connections",
// componentUnderTest (Test Plan col C), testId=TC-<n> (Test Plan col A), and
// client (UI|CLI). See https://qa.meshery.io and the meshery test-tagging docs.
const CONNECTIONS_EPIC = "Kubernetes Connections";

// Matches componentUnderTest values that denote Kubernetes connection behavior.
// Used as a fallback selector when a result predates the epic label.
const CONNECTION_COMPONENT_RE = /kubernetes/i;

// Select a result into the Connections report: prefer the explicit epic label.
// The componentUnderTest fallback applies ONLY to results that carry no epic
// label at all (tagged before the epic convention) - a result with a different
// epic value must not be pulled in just because its component is Kubernetes.
const isConnectionBehavior = (labels) => {
const hasEpic = labels.some(({ name }) => name === "epic");
if (hasEpic) {
return labels.some(
({ name, value }) => name === "epic" && value === CONNECTIONS_EPIC,
);
}
return labels.some(
({ name, value }) =>
name === "componentUnderTest" && CONNECTION_COMPONENT_RE.test(value),
);
};

export default defineConfig({
name: "Meshery Quality Dashboard",
output: "./allure-report",
Expand Down Expand Up @@ -96,6 +123,26 @@ export default defineConfig({
groupBy: ["parentSuite", "suite", "subSuite"],
},
},
// Cross-client behavior report: aggregates Kubernetes Connection tests from
// BOTH the UI (project=Meshery) and CLI (project=mesheryctl) pools. It keys
// on the epic label, NOT project, so it is an additional lens - connection
// tests still appear in the Meshery and Mesheryctl reports above.
connections: {
import: "@allurereport/plugin-awesome",
options: {
reportName: "Kubernetes Connections",
singleFile: false,
reportLanguage: "en",
open: false,
logo: "https://raw.githubusercontent.com/meshery-extensions/qa/refs/heads/master/.github/assets/images/meshery/icon-only/meshery-light-icon.svg",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving as-is here: every existing plugin in allurerc.mjs (meshery, mesheryctl, kanvas, layer5Cloud) uses this same refs/heads/master logo URL, so pinning only the new plugin to a commit SHA would diverge from the established convention. Converting all logos to pinned SHAs/tags is a worthwhile but separate, repo-wide change.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving as-is intentionally: every plugin in allurerc.mjs uses this same refs/heads/master logo URL, so pinning only the new plugin to a SHA would diverge from the file's convention. Converting all logos to pinned refs is a worthwhile separate, repo-wide change.

filter: ({ labels }) => isConnectionBehavior(labels),
// Group by client (UI vs CLI) first, then the suite hierarchy. The
// awesome plugin (preciseTreeLabels) keeps only label names present on
// at least one result, so results missing "client" fall back to the
// suite/subSuite grouping automatically.
groupBy: ["client", "suite", "subSuite"],
},
},

log: {
options: {
Expand Down