snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
Server CI Nightly Race / Build Environment (push) Failing after 1s
This commit is contained in:
265
.github/workflows/server-ci-report.yml
vendored
Normal file
265
.github/workflows/server-ci-report.yml
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
# Server CI Report is invoked via workflow_call from server-ci.yml after test jobs finish.
|
||||
name: Server CI Report
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
source-run-id:
|
||||
description: Server CI workflow run ID (for artifact download)
|
||||
required: true
|
||||
type: string
|
||||
source-event:
|
||||
description: github.event_name from the Server CI run
|
||||
required: true
|
||||
type: string
|
||||
head-commit-id:
|
||||
description: Commit ID for junit report annotations
|
||||
required: true
|
||||
type: string
|
||||
head-repository:
|
||||
description: head_repository.full_name from the Server CI run
|
||||
required: true
|
||||
type: string
|
||||
workflow-url:
|
||||
description: HTML URL of the Server CI workflow run
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
WEBHOOK_URL_FLAKY_TEST:
|
||||
required: false
|
||||
WEBHOOK_AUTH_TOKEN_FLAKY_TEST:
|
||||
required: false
|
||||
WEBHOOK_URL_FLAKY_TEST_MM:
|
||||
required: false
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
generate-report-matrix:
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
if: inputs.head-repository == github.repository
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
REPORT_MATRIX: ${{ steps.report.outputs.REPORT_MATRIX }}
|
||||
steps:
|
||||
- name: report/download-artifacts-from-PR-workflow
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
with:
|
||||
run-id: ${{ inputs.source-run-id }}
|
||||
github-token: ${{ github.token }}
|
||||
pattern: "*-test-logs"
|
||||
path: reports
|
||||
|
||||
- name: report/validate-and-prepare-data
|
||||
id: validate
|
||||
run: |
|
||||
# Create validated data file
|
||||
> /tmp/validated-tests.json
|
||||
|
||||
find "reports" -type f -name "test-name" | while read -r test_file; do
|
||||
folder=$(basename "$(dirname "$test_file")")
|
||||
test_name_raw=$(cat "$test_file" | tr -d '\n\r')
|
||||
|
||||
# Validate test name: allow alphanumeric, spaces, hyphens, underscores, parentheses, and dots
|
||||
if [[ "$test_name_raw" =~ ^[a-zA-Z0-9\ \(\)_.-]+$ ]] && [[ ${#test_name_raw} -le 100 ]]; then
|
||||
# Use jq to safely escape the test name as JSON
|
||||
test_name_escaped=$(echo -n "$test_name_raw" | jq -R .)
|
||||
echo "{\"artifact\": \"$folder\", \"name\": $test_name_escaped}" >> /tmp/validated-tests.json
|
||||
else
|
||||
echo "Warning: Skipping invalid test name in $test_file: '$test_name_raw'" >&2
|
||||
fi
|
||||
done
|
||||
|
||||
# Verify we have at least some valid tests
|
||||
if [[ ! -s /tmp/validated-tests.json ]]; then
|
||||
echo "Error: No valid test names found" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: report/generate-report-matrix
|
||||
id: report
|
||||
run: |
|
||||
# Convert validated JSON objects to matrix format
|
||||
jq -s '{ "test": . }' /tmp/validated-tests.json | tee /tmp/report-matrix
|
||||
echo REPORT_MATRIX=$(cat /tmp/report-matrix | jq --compact-output --monochrome-output) >> ${GITHUB_OUTPUT}
|
||||
|
||||
publish-report:
|
||||
runs-on: ubuntu-22.04
|
||||
name: Publish Report ${{ matrix.test.name }}
|
||||
needs:
|
||||
- generate-report-matrix
|
||||
permissions:
|
||||
actions: read
|
||||
pull-requests: write
|
||||
checks: write
|
||||
strategy:
|
||||
matrix: ${{ fromJson(needs.generate-report-matrix.outputs.REPORT_MATRIX) }}
|
||||
steps:
|
||||
- name: report/download-artifacts-from-PR-workflow
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
with:
|
||||
run-id: ${{ inputs.source-run-id }}
|
||||
github-token: ${{ github.token }}
|
||||
name: ${{ matrix.test.artifact }}
|
||||
path: ${{ matrix.test.artifact }}
|
||||
- name: report/fetch-pr-number
|
||||
if: inputs.source-event == 'pull_request'
|
||||
id: incoming-pr
|
||||
env:
|
||||
ARTIFACT: "${{ matrix.test.artifact }}"
|
||||
run: |
|
||||
if [[ -f "$ARTIFACT/pr-number" ]]; then
|
||||
pr_number=$(cat "$ARTIFACT/pr-number" | tr -d '\n\r' | grep -E '^[0-9]+$')
|
||||
if [[ -n "$pr_number" ]] && [[ ${#pr_number} -le 10 ]]; then
|
||||
echo "NUMBER=$pr_number" >> ${GITHUB_OUTPUT}
|
||||
else
|
||||
echo "Invalid PR number format" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "PR number file not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
- name: Publish test report
|
||||
id: report
|
||||
uses: mikepenz/action-junit-report@49b2ca06f62aa7ef83ae6769a2179271e160d8e4 # v6.3.1
|
||||
with:
|
||||
report_paths: ${{ matrix.test.artifact }}/report.xml
|
||||
check_name: ${{ matrix.test.name }} (Results)
|
||||
job_name: ${{ matrix.test.name }}
|
||||
commit: ${{ inputs.head-commit-id }}
|
||||
require_tests: true
|
||||
check_retries: true
|
||||
flaky_summary: true
|
||||
include_passed: true
|
||||
check_annotations: true
|
||||
|
||||
- name: Report retried tests to Mattermost channel (pull request)
|
||||
if: >-
|
||||
steps.report.outputs.flaky_summary != '<table><tr><th>Test</th><th>Retries</th></tr></table>'
|
||||
&& steps.report.outputs.failed == '0'
|
||||
&& inputs.source-event == 'pull_request'
|
||||
&& env.WEBHOOK_URL_FLAKY_TEST_MM != ''
|
||||
continue-on-error: true
|
||||
env:
|
||||
WEBHOOK_URL_FLAKY_TEST_MM: ${{ secrets.WEBHOOK_URL_FLAKY_TEST_MM }}
|
||||
FLAKY_SUMMARY: ${{ steps.report.outputs.flaky_summary }}
|
||||
PR_NUMBER: ${{ steps.incoming-pr.outputs.NUMBER }}
|
||||
TEST_NAME: ${{ matrix.test.name }}
|
||||
REPO: ${{ github.repository }}
|
||||
WORKFLOW_RUN_HTML_URL: ${{ inputs.workflow-url }}
|
||||
SERVER_URL: ${{ github.server_url }}
|
||||
run: |
|
||||
PR_URL="${SERVER_URL}/${REPO}/pull/${PR_NUMBER}"
|
||||
|
||||
# Convert the HTML <table> flaky summary into a Mattermost markdown table.
|
||||
# The summary contains a header row plus, per suite, a section-header row
|
||||
# (<td colspan="2"><strong>...</strong></td>) that markdown tables cannot
|
||||
# represent. Parse the HTML, keep only rows matching the header's column
|
||||
# count (dropping section-header rows), and emit a flat markdown table.
|
||||
TABLE_MD=$(python3 - <<'PY'
|
||||
import os, html
|
||||
from html.parser import HTMLParser
|
||||
|
||||
|
||||
class FlakyTableParser(HTMLParser):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.rows = []
|
||||
self.row = None
|
||||
self.cell = None
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
if tag == "tr":
|
||||
self.row = []
|
||||
elif tag in ("td", "th"):
|
||||
self.cell = []
|
||||
|
||||
def handle_endtag(self, tag):
|
||||
if tag in ("td", "th") and self.cell is not None:
|
||||
self.row.append("".join(self.cell))
|
||||
self.cell = None
|
||||
elif tag == "tr" and self.row is not None:
|
||||
self.rows.append(self.row)
|
||||
self.row = None
|
||||
|
||||
def handle_data(self, data):
|
||||
if self.cell is not None:
|
||||
self.cell.append(data)
|
||||
|
||||
|
||||
parser = FlakyTableParser()
|
||||
parser.feed(os.environ.get("FLAKY_SUMMARY", ""))
|
||||
|
||||
rows = parser.rows
|
||||
if rows:
|
||||
width = len(rows[0])
|
||||
# Keep header + data rows; drop colspan section-header rows.
|
||||
rows = [r for r in rows if len(r) == width]
|
||||
|
||||
|
||||
def cell(text):
|
||||
# Collapse all whitespace (incl. newlines) so a cell stays on one
|
||||
# line; otherwise an embedded newline would break the markdown row.
|
||||
text = " ".join(html.unescape(text).split())
|
||||
return text.replace("|", "\\|")
|
||||
|
||||
|
||||
if len(rows) >= 2:
|
||||
lines = ["| " + " | ".join(cell(c) for c in rows[0]) + " |",
|
||||
"|" + "|".join(["---"] * width) + "|"]
|
||||
lines += ["| " + " | ".join(cell(c) for c in r) + " |" for r in rows[1:]]
|
||||
print("\n".join(lines))
|
||||
PY
|
||||
)
|
||||
|
||||
# Use real newlines; a literal "\n" renders verbatim in Mattermost.
|
||||
NL=$'\n'
|
||||
TEXT=":warning: **Flaky test(s) detected** in [${REPO}#${PR_NUMBER}](${PR_URL})"
|
||||
TEXT="${TEXT}${NL}_Test job:_ [${TEST_NAME}](${WORKFLOW_RUN_HTML_URL})${NL}${NL}${TABLE_MD}"
|
||||
|
||||
PAYLOAD=$(jq -n \
|
||||
--arg text "$TEXT" \
|
||||
'{
|
||||
username: "Flaky Test Report",
|
||||
icon_url: "https://mattermost.com/wp-content/uploads/2022/02/icon_WS.png",
|
||||
attachments: [{color: "#CCCC00", text: $text}]
|
||||
}')
|
||||
|
||||
curl -X POST -fsSL \
|
||||
--connect-timeout 5 \
|
||||
--max-time 30 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$PAYLOAD" \
|
||||
"$WEBHOOK_URL_FLAKY_TEST_MM"
|
||||
|
||||
- name: Report retried tests to flaky-test webhook (pull request)
|
||||
if: >-
|
||||
steps.report.outputs.flaky_summary != '<table><tr><th>Test</th><th>Retries</th></tr></table>'
|
||||
&& steps.report.outputs.failed == '0'
|
||||
&& inputs.source-event == 'pull_request'
|
||||
&& env.WEBHOOK_URL_FLAKY_TEST != ''
|
||||
&& env.WEBHOOK_AUTH_TOKEN_FLAKY_TEST != ''
|
||||
continue-on-error: true
|
||||
env:
|
||||
WEBHOOK_URL_FLAKY_TEST: ${{ secrets.WEBHOOK_URL_FLAKY_TEST }}
|
||||
WEBHOOK_AUTH_TOKEN_FLAKY_TEST: ${{ secrets.WEBHOOK_AUTH_TOKEN_FLAKY_TEST }}
|
||||
FLAKY_SUMMARY: ${{ steps.report.outputs.flaky_summary }}
|
||||
PR_NUMBER: ${{ steps.incoming-pr.outputs.NUMBER }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: |
|
||||
PAYLOAD=$(jq -n \
|
||||
--arg repo "$REPO" \
|
||||
--arg pr_number "$PR_NUMBER" \
|
||||
--arg flaky_summary "$FLAKY_SUMMARY" \
|
||||
'{repo:$repo, pr_number:$pr_number, flaky_summary:$flaky_summary}')
|
||||
|
||||
curl -X POST -fsSL \
|
||||
--connect-timeout 5 \
|
||||
--max-time 30 \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $WEBHOOK_AUTH_TOKEN_FLAKY_TEST" \
|
||||
-d "$PAYLOAD" \
|
||||
"$WEBHOOK_URL_FLAKY_TEST"
|
||||
Reference in New Issue
Block a user