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:
161
e2e-tests/playwright/script/resolve_upgrade_matrix.mjs
Normal file
161
e2e-tests/playwright/script/resolve_upgrade_matrix.mjs
Normal file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env node
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// Resolves the rolling-upgrade matrix for CI: last 3 minor releases + any active Extended
|
||||
// Support release. Prints JSON objects with docker tags and ESR metadata, e.g.
|
||||
// [{"dockerTag":"release-11.9",...}] — or `[]` when no supported from-versions remain (CI posts
|
||||
// e2e-test/playwright-full/{edition}/upgrade-from-none and skips workers).
|
||||
//
|
||||
// Current version + last-3 come from this local checkout's version.go. Support-end dates and ESR
|
||||
// status are fetched live from master, since those lapse with calendar time.
|
||||
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
|
||||
const RELEASES_MDX_URL =
|
||||
'https://raw.githubusercontent.com/mattermost/mattermost/refs/heads/master/docs/main/product-overview/mattermost-server-releases.mdx';
|
||||
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const VERSION_GO_PATH = path.resolve(currentDir, '../../../server/public/model/version.go');
|
||||
|
||||
// Named (not inline) so referencing `.test()` below is unambiguous to both eslint and Prettier.
|
||||
const RELEASE_ROW_PATTERN = /^\|\s*v\d+\.\d+\s/;
|
||||
const CELL_SEPARATOR_PATTERN = /(?<!\\)\|/;
|
||||
|
||||
function toMinor(version) {
|
||||
const [major, minor] = version.split('.');
|
||||
return `${major}.${minor}`;
|
||||
}
|
||||
|
||||
/** Numeric major.minor ordering — string compare would sort 11.9 after 11.10. */
|
||||
function compareMinor(a, b) {
|
||||
const [aMajor, aMinor] = a.split('.').map(Number);
|
||||
const [bMajor, bMinor] = b.split('.').map(Number);
|
||||
return aMajor - bMajor || aMinor - bMinor;
|
||||
}
|
||||
|
||||
/** Maps a release patch version to the registry's floating minor tag. */
|
||||
function toDockerImageTag(patchVersion) {
|
||||
const [major, minor] = patchVersion.split('.');
|
||||
return `release-${major}.${minor}`;
|
||||
}
|
||||
|
||||
/** GitHub commit-status / dashboard label for a matrix entry. */
|
||||
export function upgradeMatrixContextLabel(entry) {
|
||||
return entry.isESR ? `${entry.dockerTag}-esr` : entry.dockerTag;
|
||||
}
|
||||
|
||||
/** Reads current + last-3-minor versions from the local checkout's version.go. */
|
||||
function readLocalVersions() {
|
||||
const source = fs.readFileSync(VERSION_GO_PATH, 'utf-8');
|
||||
const block = source.match(/var versions = \[\]string\{([^}]*)\}/);
|
||||
if (!block) {
|
||||
throw new Error(`Could not find "var versions = []string{...}" block in ${VERSION_GO_PATH}`);
|
||||
}
|
||||
const versions = [...block[1].matchAll(/"([\d.]+)"/g)].map((m) => m[1]);
|
||||
|
||||
// Release branches list every hotfix of their own minor first ("11.9.2", "11.9.1", "11.9.0",
|
||||
// "11.8.0", ...), so collapse to unique minors before slicing. Taking the raw entries would
|
||||
// make lastThree on release-11.9 read 11.9, 11.9, 11.8 — offering the branch its own version
|
||||
// as an upgrade source and dropping a genuinely older one.
|
||||
const minors = [...new Set(versions.map(toMinor))];
|
||||
if (minors.length < 4) {
|
||||
throw new Error(`Expected at least 4 distinct minors in ${VERSION_GO_PATH}, found ${minors.length}`);
|
||||
}
|
||||
return {
|
||||
current: minors[0],
|
||||
lastThree: minors.slice(1, 4),
|
||||
};
|
||||
}
|
||||
|
||||
/** Fetches and parses the releases table's rows into {minor, patch, supportEnds, isESR}. */
|
||||
async function fetchReleaseRows() {
|
||||
const response = await fetch(RELEASES_MDX_URL);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch ${RELEASES_MDX_URL}: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
const mdx = await response.text();
|
||||
|
||||
const rows = [];
|
||||
for (const line of mdx.split('\n')) {
|
||||
if (!RELEASE_ROW_PATTERN.test(line)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cell separators are unescaped `|`; the first cell's own markdown link text contains
|
||||
// escaped `\|` between [Download]/[Changelog]/SBOM links, which CELL_SEPARATOR_PATTERN's
|
||||
// lookbehind skips.
|
||||
const rawCells = line.split(CELL_SEPARATOR_PATTERN);
|
||||
const cells = rawCells.map((cell) => cell.trim()).filter(Boolean);
|
||||
if (cells.length < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const [releaseCell, , supportEndsCell] = cells;
|
||||
|
||||
const minorMatch = releaseCell.match(/^v(\d+\.\d+)/);
|
||||
const patchMatch = releaseCell.match(/releases\.mattermost\.com\/(\d+\.\d+\.\d+)\//);
|
||||
const dateMatch = supportEndsCell.match(/(\d{4}-\d{2}-\d{2})/);
|
||||
if (!minorMatch || !patchMatch || !dateMatch) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rows.push({
|
||||
minor: minorMatch[1],
|
||||
patch: patchMatch[1],
|
||||
supportEnds: new Date(dateMatch[1]),
|
||||
isESR: supportEndsCell.includes('[EXTENDED]'),
|
||||
});
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
export async function resolveUpgradeMatrix(now = new Date()) {
|
||||
const {current, lastThree} = readLocalVersions();
|
||||
const rows = await fetchReleaseRows();
|
||||
|
||||
const active = rows.filter((row) => row.supportEnds > now);
|
||||
|
||||
// Only strictly older minors are upgrade sources. The ESR clause below is otherwise unbounded:
|
||||
// cutting release-11.7 while 11.7 is the active ESR would put 11.7 in its own matrix, which is
|
||||
// a no-op upgrade rather than coverage.
|
||||
const older = active.filter((row) => compareMinor(row.minor, current) < 0);
|
||||
const matrix = older.filter((row) => lastThree.includes(row.minor) || row.isESR);
|
||||
|
||||
const seenMinors = new Set();
|
||||
const entries = [];
|
||||
for (const row of matrix) {
|
||||
if (seenMinors.has(row.minor)) {
|
||||
continue;
|
||||
}
|
||||
seenMinors.add(row.minor);
|
||||
const dockerTag = toDockerImageTag(row.patch);
|
||||
entries.push({
|
||||
dockerTag,
|
||||
minor: row.minor,
|
||||
patch: row.patch,
|
||||
isESR: row.isESR,
|
||||
contextLabel: upgradeMatrixContextLabel({dockerTag, isESR: row.isESR}),
|
||||
});
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const entries = await resolveUpgradeMatrix();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(JSON.stringify(entries));
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
main().catch((error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(String(error));
|
||||
|
||||
// Rethrow (not process.exit()) — an unhandled rejection still exits non-zero, which is
|
||||
// all CI/local invocations need to fail loudly.
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user