From 540401586e2f4fdcdd51dfb5c7f0af58931b9dee Mon Sep 17 00:00:00 2001 From: Unnati Solanki Date: Sat, 19 Sep 2026 20:24:23 +0530 Subject: [PATCH 1/7] [patch] Update the GHE linking to FVT --- image/cli/app-root/src/finalizer.py | 74 ++++++++++++++++++++ image/cli/install/install-python-packages.sh | 3 + tekton/src/tasks/fvt/mas-fvt-finalize.yml.j2 | 6 ++ 3 files changed, 83 insertions(+) diff --git a/image/cli/app-root/src/finalizer.py b/image/cli/app-root/src/finalizer.py index d36c464ee7f..32eeb9fbfb7 100644 --- a/image/cli/app-root/src/finalizer.py +++ b/image/cli/app-root/src/finalizer.py @@ -15,6 +15,7 @@ from kubernetes.client import Configuration from openshift.dynamic import DynamicClient from mas.devops.slack import SlackUtil +from mas.toolchain.github.checks import createCheckRun, updateCheckRun from subprocess import PIPE, Popen, TimeoutExpired from mobilever import MobVer import threading @@ -164,6 +165,62 @@ def getcp4dCompsVersions(): print(f"Unable to determine Cognos Analytics version: {e}") +# GHE repo slugs for each product operator — used to post check runs against +# the commit that was deployed when FVT ran. +# Format: productId (as used in knownProductIds) -> "org/repo" on github.ibm.com +# ----------------------------------------------------------------------------- +PRODUCT_REPO_SLUGS = { + "ibm-mas": "maximoappsuite/ibm-mas", + "ibm-mas-assist": "maximoappsuite/ibm-mas-assist", + "ibm-mas-iot": "maximoappsuite/ibm-mas-iot", + "ibm-mas-manage": "maximoappsuite/ibm-mas-manage", + "ibm-mas-facilities": "maximoappsuite/ibm-mas-facilities", + "ibm-mas-monitor": "maximoappsuite/ibm-mas-monitor", + "ibm-mas-optimizer": "maximoappsuite/ibm-mas-optimizer", + "ibm-mas-predict": "maximoappsuite/ibm-mas-predict", + "ibm-mas-visualinspection": "maximoappsuite/ibm-mas-visualinspection", + "ibm-mas-data-dictionary": "maximoappsuite/ibm-mas-data-dictionary", + "ibm-sls": "maximoappsuite/ibm-sls", + "ibm-aiservice": "maximoappsuite/ibm-aiservice", +} + +CHECK_RUN_NAME = "FVT Results" + + +def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId): + """Post a GHE check run against the product repo commit that was under test. + + Phase 1: simply links the FVT run back to the commit — no detailed output yet. + The check always completes as 'neutral' so it is purely informational and does + not block PRs or merges. + + Args: + productId (str): e.g. 'ibm-mas-manage' + commitId (str): full SHA from the mas.ibm.com/commitId deployment label + repoSlug (str): 'org/repo' on github.ibm.com + detailsUrl (str): URL of the FVT dashboard run (used as the 'Details' link) + runId (str): human-readable run identifier, e.g. 'fvt92x:42' + """ + try: + check_run_id = createCheckRun( + name=CHECK_RUN_NAME, + repoSlug=repoSlug, + commitSha=commitId, + detailsUrl=detailsUrl, + ) + updateCheckRun( + checkRunId=check_run_id, + repoSlug=repoSlug, + conclusion="neutral", + detailsUrl=detailsUrl, + outputTitle="FVT run linked", + outputSummary=f"This commit was included in FVT run [{runId}]({detailsUrl}).", + ) + print(f"GHE check run posted: {repoSlug}@{commitId[:8]} [{CHECK_RUN_NAME}]") + except Exception as e: + print(f"Failed to post GHE check run for {productId} ({repoSlug}@{commitId[:8]}): {e}") + + # Script start # ----------------------------------------------------------------------------- if __name__ == "__main__": @@ -625,6 +682,23 @@ def getcp4dCompsVersions(): else: print("Run information NOT updated in MongoDb because DRY_RUN is set") + # Publish GHE check runs linked to each product repo commit + # Only runs when the build is finished and the GHE App key is available. + # Failures here are non-fatal — they print a warning and the script continues. + # ------------------------------------------------------------------------- + if setFinished.lower() == "true" and os.getenv("GITHUB_APP_PRIVATE_KEY"): + details_url = os.getenv("TOOLCHAIN_PIPELINERUN_URL", f"https://dashboard.ibmmas.com/tests/{instanceId}") + for productId, repoSlug in PRODUCT_REPO_SLUGS.items(): + commitId = setObject.get(f"products.{productId}.commitId") + if not commitId: + print(f"No commitId for {productId}, skipping GHE check run") + continue + publish_fvt_check_run(productId, commitId, repoSlug, details_url, runId) + elif setFinished.lower() != "true": + print("FVT run not yet finished, skipping GHE check runs") + else: + print("GITHUB_APP_PRIVATE_KEY not set, skipping GHE check runs") + # Check pre-reqs for Slack integration # ------------------------------------------------------------------------- SLACK_TOKEN = os.getenv("SLACK_TOKEN") diff --git a/image/cli/install/install-python-packages.sh b/image/cli/install/install-python-packages.sh index d65a5e6a268..7040666e754 100644 --- a/image/cli/install/install-python-packages.sh +++ b/image/cli/install/install-python-packages.sh @@ -5,6 +5,9 @@ python3 -m pip install pip --upgrade # We always install the version of the mas-cli package that we just built python3 -m pip install /tmp/install/mas_cli.tar.gz +# Install mas-toolchain for GHE Checks API integration (used by finalizer.py) +python3 -m pip install mas-toolchain + if [[ -e /tmp/install/mas_devops.tar.gz ]]; then # If we have copied a pre-built version of the mas_devops collection then use that, # otherwise we will use the latest version that was installed when we installed the mas-cli package above diff --git a/tekton/src/tasks/fvt/mas-fvt-finalize.yml.j2 b/tekton/src/tasks/fvt/mas-fvt-finalize.yml.j2 index e67617b6c84..9e13a72a9ed 100644 --- a/tekton/src/tasks/fvt/mas-fvt-finalize.yml.j2 +++ b/tekton/src/tasks/fvt/mas-fvt-finalize.yml.j2 @@ -44,3 +44,9 @@ spec: name: mas-fvt key: FVT_JIRA_TOKEN optional: true + - name: GITHUB_APP_PRIVATE_KEY + valueFrom: + secretKeyRef: + name: mas-fvt + key: GITHUB_APP_PRIVATE_KEY + optional: true From 71f2169fb9c4785b0265daac3a0fea433331565c Mon Sep 17 00:00:00 2001 From: Unnati Solanki Date: Mon, 21 Sep 2026 20:37:49 +0530 Subject: [PATCH 2/7] [patch] Reference GHE methods --- image/cli/app-root/src/finalizer.py | 2 +- image/cli/install/install-python-packages.sh | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/image/cli/app-root/src/finalizer.py b/image/cli/app-root/src/finalizer.py index 32eeb9fbfb7..4f5900a65b2 100644 --- a/image/cli/app-root/src/finalizer.py +++ b/image/cli/app-root/src/finalizer.py @@ -15,7 +15,7 @@ from kubernetes.client import Configuration from openshift.dynamic import DynamicClient from mas.devops.slack import SlackUtil -from mas.toolchain.github.checks import createCheckRun, updateCheckRun +from mas.devops.github import createCheckRun, updateCheckRun from subprocess import PIPE, Popen, TimeoutExpired from mobilever import MobVer import threading diff --git a/image/cli/install/install-python-packages.sh b/image/cli/install/install-python-packages.sh index 7040666e754..d65a5e6a268 100644 --- a/image/cli/install/install-python-packages.sh +++ b/image/cli/install/install-python-packages.sh @@ -5,9 +5,6 @@ python3 -m pip install pip --upgrade # We always install the version of the mas-cli package that we just built python3 -m pip install /tmp/install/mas_cli.tar.gz -# Install mas-toolchain for GHE Checks API integration (used by finalizer.py) -python3 -m pip install mas-toolchain - if [[ -e /tmp/install/mas_devops.tar.gz ]]; then # If we have copied a pre-built version of the mas_devops collection then use that, # otherwise we will use the latest version that was installed when we installed the mas-cli package above From 2109efbc9ecc35bbf83cda0e23470c34e2a0f79d Mon Sep 17 00:00:00 2001 From: Unnati Solanki Date: Fri, 25 Sep 2026 12:26:14 +0530 Subject: [PATCH 3/7] [patch] Formatting on GHE check --- image/cli/app-root/src/finalizer.py | 98 +++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/image/cli/app-root/src/finalizer.py b/image/cli/app-root/src/finalizer.py index 82c85cdc470..9e5d0b9a517 100644 --- a/image/cli/app-root/src/finalizer.py +++ b/image/cli/app-root/src/finalizer.py @@ -185,26 +185,84 @@ def getcp4dCompsVersions(): "ibm-aiservice": "maximoappsuite/ibm-aiservice", } -CHECK_RUN_NAME = "FVT Results" - -def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId): +def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, productData): """Post a GHE check run against the product repo commit that was under test. - Phase 1: simply links the FVT run back to the commit — no detailed output yet. - The check always completes as 'neutral' so it is purely informational and does - not block PRs or merges. + The check always completes as 'neutral' — informational only, never blocks PRs. Args: - productId (str): e.g. 'ibm-mas-manage' - commitId (str): full SHA from the mas.ibm.com/commitId deployment label - repoSlug (str): 'org/repo' on github.ibm.com - detailsUrl (str): URL of the FVT dashboard run (used as the 'Details' link) - runId (str): human-readable run identifier, e.g. 'fvt92x:42' + productId (str): e.g. 'ibm-mas-manage' + commitId (str): full SHA from the mas.ibm.com/commitId deployment label + repoSlug (str): 'org/repo' on github.ibm.com + detailsUrl (str): URL of the FVT dashboard run (used as the Details link) + runId (str): human-readable run identifier, e.g. 'usfvt:5124' + productData (dict): product entry from the MongoDB run document """ + version = productData.get("version", "unknown") + instanceId, build = runId.split(":", 1) + checkName = f"FVT / {productId}" + + # Aggregate totals and build per-suite table rows + total_tests = total_failures = total_errors = total_skipped = 0 + suite_rows = [] + for suite, r in sorted(productData.get("results", {}).items()): + t, f, e, s = r.get("tests", 0), r.get("failures", 0), r.get("errors", 0), r.get("skipped", 0) + total_tests += t + total_failures += f + total_errors += e + total_skipped += s + icon = "🔴" if f > 0 else ("🟡" if e > 0 else "🟢") + suite_url = f"https://dashboard.ibmmas.com/tests/{instanceId}/testsuite/{productId}/{suite}" + suite_rows.append(f"| {icon} [{suite}]({suite_url}) | {t} | {f} | {e} | {s} |") + + # Title — single line shown in the checks list on the commit page + if total_tests == 0: + output_title = f"{productId} — no test results recorded" + elif total_failures > 0 or total_errors > 0: + output_title = f"{productId} v{version} — {total_failures} failures, {total_errors} errors across {total_tests} tests" + else: + output_title = f"{productId} v{version} — all {total_tests} tests passed" + + # Body — full markdown rendered on the check run detail page + dashboard_url = f"https://dashboard.ibmmas.com/tests/{instanceId}" + lines = [ + f"## FVT Results — `{productId}`", + "", + "> This check is automatically posted by the MAS Functional Verification Test (FVT) pipeline.", + f"> It shows the test outcome for the exact commit that was deployed and tested on environment **{instanceId}**.", + "", + "---", + "", + "| | |", + "| --- | --- |", + f"| **Product** | `{productId}` v{version} |", + f"| **Run** | [{instanceId}#{build}]({dashboard_url}) |", + f"| **Commit** | `{commitId[:12]}` |", + f"| **Results** | {total_tests} tests · {total_failures} failures · {total_errors} errors · {total_skipped} skipped |", + "", + ] + + if suite_rows: + lines += [ + "### Suite Breakdown", + "", + "| Suite | Tests | Failures | Errors | Skipped |", + "| ----- | ----: | -------: | -----: | ------: |", + ] + suite_rows + else: + lines.append("_No suite results were recorded for this product in this run._") + + lines += [ + "", + "---", + "", + f"[View full results on the FVT Dashboard]({detailsUrl})", + ] + try: check_run_id = createCheckRun( - name=CHECK_RUN_NAME, + name=checkName, repoSlug=repoSlug, commitSha=commitId, detailsUrl=detailsUrl, @@ -214,10 +272,10 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId): repoSlug=repoSlug, conclusion="neutral", detailsUrl=detailsUrl, - outputTitle="FVT run linked", - outputSummary=f"This commit was included in FVT run [{runId}]({detailsUrl}).", + outputTitle=output_title, + outputSummary="\n".join(lines), ) - print(f"GHE check run posted: {repoSlug}@{commitId[:8]} [{CHECK_RUN_NAME}]") + print(f"GHE check run posted: {repoSlug}@{commitId[:8]} [{checkName}]") except Exception as e: print(f"Failed to post GHE check run for {productId} ({repoSlug}@{commitId[:8]}): {e}") @@ -695,17 +753,19 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId): print("Run information NOT updated in MongoDb because DRY_RUN is set") # Publish GHE check runs linked to each product repo commit - # Only runs when the build is finished and the GHE App key is available. - # Failures here are non-fatal — they print a warning and the script continues. + # Runs independently of Slack/Jira — only needs GITHUB_APP_PRIVATE_KEY and MongoDB. + # Failures are non-fatal — never aborts the rest of the script. # ------------------------------------------------------------------------- if setFinished.lower() == "true" and os.getenv("GITHUB_APP_PRIVATE_KEY"): details_url = os.getenv("TOOLCHAIN_PIPELINERUN_URL", f"https://dashboard.ibmmas.com/tests/{instanceId}") + ghe_result = db.runsv2.find_one({"_id": runId}) for productId, repoSlug in PRODUCT_REPO_SLUGS.items(): - commitId = setObject.get(f"products.{productId}.commitId") + productData = ghe_result.get("products", {}).get(productId, {}) if ghe_result else {} + commitId = productData.get("commitId") if not commitId: print(f"No commitId for {productId}, skipping GHE check run") continue - publish_fvt_check_run(productId, commitId, repoSlug, details_url, runId) + publish_fvt_check_run(productId, commitId, repoSlug, details_url, runId, productData) elif setFinished.lower() != "true": print("FVT run not yet finished, skipping GHE check runs") else: From 685518df1421680346722696dd76bd71d2fc4efa Mon Sep 17 00:00:00 2001 From: Unnati Solanki Date: Fri, 25 Sep 2026 21:11:03 +0530 Subject: [PATCH 4/7] [patch] Address review comments --- image/cli/app-root/src/finalizer.py | 116 ++++++++++++++++++++-------- 1 file changed, 85 insertions(+), 31 deletions(-) diff --git a/image/cli/app-root/src/finalizer.py b/image/cli/app-root/src/finalizer.py index 9e5d0b9a517..9a19d836815 100644 --- a/image/cli/app-root/src/finalizer.py +++ b/image/cli/app-root/src/finalizer.py @@ -15,7 +15,7 @@ from kubernetes.client import Configuration from openshift.dynamic import DynamicClient from mas.devops.slack import SlackUtil -from mas.devops.github import createCheckRun, updateCheckRun +from mas.devops.github import createCheckRun, updateCheckRun, findCheckRun from mas.devops.mas import getPermissionMode from subprocess import PIPE, Popen, TimeoutExpired from mobilever import MobVer @@ -186,10 +186,16 @@ def getcp4dCompsVersions(): } -def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, productData): - """Post a GHE check run against the product repo commit that was under test. +def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, productData, runDoc): + """Post (or update) a GHE check run against the product repo commit that was under test. - The check always completes as 'neutral' — informational only, never blocks PRs. + Check name is 'FVT Results / {instanceId}' so each environment gets its own + distinct check on the commit. If a check with that name already exists on the + commit it is updated in-place rather than creating a duplicate. + + Conclusion is 'failure' when there are test failures/errors (visible indicator + for developers), but the check is never added to branch protection rules so it + will never block a PR merge. Args: productId (str): e.g. 'ibm-mas-manage' @@ -198,10 +204,18 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod detailsUrl (str): URL of the FVT dashboard run (used as the Details link) runId (str): human-readable run identifier, e.g. 'usfvt:5124' productData (dict): product entry from the MongoDB run document + runDoc (dict): full MongoDB run document (for run-level fields like timestamp) """ version = productData.get("version", "unknown") instanceId, build = runId.split(":", 1) - checkName = f"FVT / {productId}" + checkName = f"FVT Results / {instanceId}" + + # Format run timestamp — shown in the heading as e.g. "Sep 25 09:31" + run_ts = runDoc.get("timestamp") if runDoc else None + if run_ts: + build_date = run_ts.strftime("%b %d %H:%M") + else: + build_date = "" # Aggregate totals and build per-suite table rows total_tests = total_failures = total_errors = total_skipped = 0 @@ -216,18 +230,34 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod suite_url = f"https://dashboard.ibmmas.com/tests/{instanceId}/testsuite/{productId}/{suite}" suite_rows.append(f"| {icon} [{suite}]({suite_url}) | {t} | {f} | {e} | {s} |") + # Conclusion — failure when tests failed/errored so developers get a clear + # red indicator on the commit, but this check is never added to branch + # protection rules so it will never block a PR merge. + if total_failures > 0 or total_errors > 0: + conclusion = "failure" + status_icon = "❌" + else: + conclusion = "success" + status_icon = "✅" + # Title — single line shown in the checks list on the commit page if total_tests == 0: - output_title = f"{productId} — no test results recorded" + output_title = f"No test results recorded for {instanceId} #{build}" elif total_failures > 0 or total_errors > 0: - output_title = f"{productId} v{version} — {total_failures} failures, {total_errors} errors across {total_tests} tests" + output_title = f"{total_failures} failures, {total_errors} errors — {total_tests} tests run on {instanceId} #{build}" else: - output_title = f"{productId} v{version} — all {total_tests} tests passed" + output_title = f"All {total_tests} tests passed on {instanceId} #{build}" + + # Heading line — status icon + instance + build + date + heading_parts = [f"{status_icon} FVT Results — {instanceId} #{build}"] + if build_date: + heading_parts.append(f"| {build_date}") + heading = " ".join(heading_parts) - # Body — full markdown rendered on the check run detail page + # Body — full markdown rendered on the check run detail pages dashboard_url = f"https://dashboard.ibmmas.com/tests/{instanceId}" lines = [ - f"## FVT Results — `{productId}`", + f"## {heading}", "", "> This check is automatically posted by the MAS Functional Verification Test (FVT) pipeline.", f"> It shows the test outcome for the exact commit that was deployed and tested on environment **{instanceId}**.", @@ -261,21 +291,35 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod ] try: - check_run_id = createCheckRun( - name=checkName, - repoSlug=repoSlug, - commitSha=commitId, - detailsUrl=detailsUrl, - ) - updateCheckRun( - checkRunId=check_run_id, - repoSlug=repoSlug, - conclusion="neutral", - detailsUrl=detailsUrl, - outputTitle=output_title, - outputSummary="\n".join(lines), - ) - print(f"GHE check run posted: {repoSlug}@{commitId[:8]} [{checkName}]") + # Upsert — update existing check run for this instance+commit if one exists, + # otherwise create a new one. Prevents duplicate checks on repeat runs. + existing_id = findCheckRun(name=checkName, repoSlug=repoSlug, commitSha=commitId) + if existing_id: + updateCheckRun( + checkRunId=existing_id, + repoSlug=repoSlug, + conclusion=conclusion, + detailsUrl=detailsUrl, + outputTitle=output_title, + outputSummary="\n".join(lines), + ) + print(f"GHE check run updated: {repoSlug}@{commitId[:8]} [{checkName}] (id={existing_id})") + else: + check_run_id = createCheckRun( + name=checkName, + repoSlug=repoSlug, + commitSha=commitId, + detailsUrl=detailsUrl, + ) + updateCheckRun( + checkRunId=check_run_id, + repoSlug=repoSlug, + conclusion=conclusion, + detailsUrl=detailsUrl, + outputTitle=output_title, + outputSummary="\n".join(lines), + ) + print(f"GHE check run posted: {repoSlug}@{commitId[:8]} [{checkName}] (id={check_run_id})") except Exception as e: print(f"Failed to post GHE check run for {productId} ({repoSlug}@{commitId[:8]}): {e}") @@ -754,9 +798,23 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod # Publish GHE check runs linked to each product repo commit # Runs independently of Slack/Jira — only needs GITHUB_APP_PRIVATE_KEY and MongoDB. + # Only runs for instances in GHE_FVT_INSTANCES (comma-separated env var). + # Falls back to a hardcoded default list when the env var is not set. # Failures are non-fatal — never aborts the rest of the script. # ------------------------------------------------------------------------- - if setFinished.lower() == "true" and os.getenv("GITHUB_APP_PRIVATE_KEY"): + _DEFAULT_GHE_INSTANCES = ["fvtstable", "fvtcpd", "uscpd", "usfvt"] + ghe_instances_raw = os.getenv("GHE_FVT_INSTANCES", "") + ghe_instances = [i.strip() for i in ghe_instances_raw.split(",") if i.strip()] or _DEFAULT_GHE_INSTANCES + + if not os.getenv("GITHUB_APP_PRIVATE_KEY"): + print("GITHUB_APP_PRIVATE_KEY not set, skipping GHE check runs") + elif setFinished.lower() != "true": + print("FVT run not yet finished, skipping GHE check runs") + elif not ghe_instances: + print("GHE_FVT_INSTANCES not set, skipping GHE check runs") + elif instanceId not in ghe_instances: + print(f"Instance '{instanceId}' not in GHE_FVT_INSTANCES, skipping GHE check runs") + else: details_url = os.getenv("TOOLCHAIN_PIPELINERUN_URL", f"https://dashboard.ibmmas.com/tests/{instanceId}") ghe_result = db.runsv2.find_one({"_id": runId}) for productId, repoSlug in PRODUCT_REPO_SLUGS.items(): @@ -765,11 +823,7 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod if not commitId: print(f"No commitId for {productId}, skipping GHE check run") continue - publish_fvt_check_run(productId, commitId, repoSlug, details_url, runId, productData) - elif setFinished.lower() != "true": - print("FVT run not yet finished, skipping GHE check runs") - else: - print("GITHUB_APP_PRIVATE_KEY not set, skipping GHE check runs") + publish_fvt_check_run(productId, commitId, repoSlug, details_url, runId, productData, ghe_result) # Check pre-reqs for Slack integration # ------------------------------------------------------------------------- From 0631a05602440154aca14c407073fde70bae1f2c Mon Sep 17 00:00:00 2001 From: Unnati Solanki Date: Fri, 25 Sep 2026 22:36:34 +0530 Subject: [PATCH 5/7] [patch] format the changes --- image/cli/app-root/src/finalizer.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/image/cli/app-root/src/finalizer.py b/image/cli/app-root/src/finalizer.py index 9a19d836815..7089f31e343 100644 --- a/image/cli/app-root/src/finalizer.py +++ b/image/cli/app-root/src/finalizer.py @@ -240,24 +240,24 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod conclusion = "success" status_icon = "✅" - # Title — single line shown in the checks list on the commit page + # Title (output.title) — rendered by GHE as a large heading above the body. + # This is the ❌/✅ status line the user sees first. + # Use "{instanceId}#{build}" with no space so GitHub doesn't auto-link #build as a PR. + build_date_suffix = f" | {build_date}" if build_date else "" + output_title = f"{status_icon} FVT Results — {instanceId}#{build}{build_date_suffix}" + + # Subtitle (first line of output.summary body) — the stats line shown below the title. if total_tests == 0: - output_title = f"No test results recorded for {instanceId} #{build}" + stats_line = f"No test results recorded for {instanceId} #{build}" elif total_failures > 0 or total_errors > 0: - output_title = f"{total_failures} failures, {total_errors} errors — {total_tests} tests run on {instanceId} #{build}" + stats_line = f"{total_failures} failures, {total_errors} errors — {total_tests} tests run on {instanceId} #{build}" else: - output_title = f"All {total_tests} tests passed on {instanceId} #{build}" - - # Heading line — status icon + instance + build + date - heading_parts = [f"{status_icon} FVT Results — {instanceId} #{build}"] - if build_date: - heading_parts.append(f"| {build_date}") - heading = " ".join(heading_parts) + stats_line = f"All {total_tests} tests passed on {instanceId} #{build}" - # Body — full markdown rendered on the check run detail pages + # Body — full markdown rendered on the check run detail page. dashboard_url = f"https://dashboard.ibmmas.com/tests/{instanceId}" lines = [ - f"## {heading}", + f"**{stats_line}**", "", "> This check is automatically posted by the MAS Functional Verification Test (FVT) pipeline.", f"> It shows the test outcome for the exact commit that was deployed and tested on environment **{instanceId}**.", From 6595c091bbfcaecaa6091617e3b652110832e2f9 Mon Sep 17 00:00:00 2001 From: Unnati Solanki Date: Fri, 25 Sep 2026 22:56:53 +0530 Subject: [PATCH 6/7] [patch] Enable checks for fvtcore and fvtcpd --- image/cli/app-root/src/finalizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image/cli/app-root/src/finalizer.py b/image/cli/app-root/src/finalizer.py index 7089f31e343..341ae60508b 100644 --- a/image/cli/app-root/src/finalizer.py +++ b/image/cli/app-root/src/finalizer.py @@ -802,7 +802,7 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod # Falls back to a hardcoded default list when the env var is not set. # Failures are non-fatal — never aborts the rest of the script. # ------------------------------------------------------------------------- - _DEFAULT_GHE_INSTANCES = ["fvtstable", "fvtcpd", "uscpd", "usfvt"] + _DEFAULT_GHE_INSTANCES = ["fvtcore", "fvtcpd"] ghe_instances_raw = os.getenv("GHE_FVT_INSTANCES", "") ghe_instances = [i.strip() for i in ghe_instances_raw.split(",") if i.strip()] or _DEFAULT_GHE_INSTANCES From d02615f159485b9ce4006c61f8f196c1409e604b Mon Sep 17 00:00:00 2001 From: Unnati Solanki Date: Fri, 25 Sep 2026 23:05:05 +0530 Subject: [PATCH 7/7] [patch] Update the check name --- image/cli/app-root/src/finalizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/image/cli/app-root/src/finalizer.py b/image/cli/app-root/src/finalizer.py index 341ae60508b..aec27d8d641 100644 --- a/image/cli/app-root/src/finalizer.py +++ b/image/cli/app-root/src/finalizer.py @@ -208,7 +208,7 @@ def publish_fvt_check_run(productId, commitId, repoSlug, detailsUrl, runId, prod """ version = productData.get("version", "unknown") instanceId, build = runId.split(":", 1) - checkName = f"FVT Results / {instanceId}" + checkName = f"FVT Results Check ({instanceId})" # Format run timestamp — shown in the heading as e.g. "Sep 25 09:31" run_ts = runDoc.get("timestamp") if runDoc else None