From 4230499b43c7800a9beb2b44a478251cdbe877e6 Mon Sep 17 00:00:00 2001 From: Hannes Wellmann Date: Tue, 20 Jan 2026 20:39:28 +0100 Subject: [PATCH] Streamline and clean-up overview section of build websites - Rearrange sections, improve labels and remove unnecessary text - Beautify TOC styling - Unify and improve display of runtimes - Drop repo image - Unify styling of lists --- JenkinsJobs/Builds/build.jenkinsfile | 6 +- JenkinsJobs/Builds/markBuild.jenkinsfile | 2 +- scripts/releng/BuildDropDataGenerator.java | 18 +--- sites/.gitignore | 6 ++ sites/eclipse/.gitignore | 2 - sites/eclipse/build/buildlogs/logs.html | 4 +- sites/eclipse/build/index.html | 65 ++++++------- sites/eclipse/build/repo.gif | Bin 353 -> 0 bytes sites/eclipse/build/reports.html | 2 +- sites/eclipse/build/testresults/logs.html | 6 +- sites/eclipse/page.css | 38 +++++++- sites/eclipse/page.js | 102 +++++++++++---------- sites/eclipse/testDataFetch.sh | 6 +- sites/equinox/.gitignore | 1 - sites/equinox/build/index.html | 15 +-- sites/equinox/build/repo.gif | Bin 353 -> 0 bytes 16 files changed, 142 insertions(+), 131 deletions(-) create mode 100644 sites/.gitignore delete mode 100644 sites/eclipse/.gitignore delete mode 100644 sites/eclipse/build/repo.gif delete mode 100644 sites/equinox/.gitignore delete mode 100644 sites/equinox/build/repo.gif diff --git a/JenkinsJobs/Builds/build.jenkinsfile b/JenkinsJobs/Builds/build.jenkinsfile index c04b4d5df65..1b458af1852 100644 --- a/JenkinsJobs/Builds/build.jenkinsfile +++ b/JenkinsJobs/Builds/build.jenkinsfile @@ -452,7 +452,7 @@ pipeline { sh '''#!/bin/bash -xe dropDir=${DROP_DIR}/${BUILD_ID} if [ -n "${COMPARATOR_ERRORS_SUBJECT}" ]; then - echo "

This build has been marked unstable due to unanticipated comparator errors

" > ${dropDir}/buildUnstable + echo "This build has been marked unstable due to unanticipated comparator errors." > ${dropDir}/buildUnstable fi scp -r ${dropDir} genie.releng@projects-storage.eclipse.org:${EP_ECLIPSE_DROPS}/. ''' @@ -542,7 +542,7 @@ pipeline { sh '''#!/bin/bash -xe dropDir=${EQUINOX_DROP_DIR}/${BUILD_ID} if [ -n "${COMPARATOR_ERRORS_SUBJECT}" ]; then - echo "

This build has been marked unstable due to unanticipated comparator errors

" > ${dropDir}/buildUnstable + echo "This build has been marked unstable due to unanticipated comparator errors." > ${dropDir}/buildUnstable fi scp -r ${dropDir} genie.releng@projects-storage.eclipse.org:${EP_EQUINOX_DROPS}/. ''' @@ -656,7 +656,7 @@ pipeline { https://download.eclipse.org/eclipse/downloads/drops4/${BUILD_ID} Build logs and/or test results (eventually): - https://download.eclipse.org/eclipse/downloads/drops4/${BUILD_ID}/reports.html#tests + https://download.eclipse.org/eclipse/downloads/drops4/${BUILD_ID}/reports.html """ + (env.COMPARATOR_ERRORS_SUBJECT == '' ? '' : """ Check unanticipated comparator messages: https://download.eclipse.org/eclipse/downloads/drops4/${BUILD_ID}/buildlogs/comparatorlogs/buildtimeComparatorUnanticipated.log.txt diff --git a/JenkinsJobs/Builds/markBuild.jenkinsfile b/JenkinsJobs/Builds/markBuild.jenkinsfile index 774f464c9e8..5618968f41d 100644 --- a/JenkinsJobs/Builds/markBuild.jenkinsfile +++ b/JenkinsJobs/Builds/markBuild.jenkinsfile @@ -46,7 +46,7 @@ pipeline { # Convert URL of GH issue or PR into: 'organization/repository#number' label=$(echo "${issueURL##'https://github.com/'}" | sed 's/\\/issues\\//#/g' | sed 's/\\/pull\\//#/g') #Add unstable tag - echo "

This build is marked unstable due to ${label}.

" > buildUnstable + echo "This build is marked unstable due to ${label}." > buildUnstable scp buildUnstable genie.releng@projects-storage.eclipse.org:${EP_BUILD_DROP}/buildUnstable ;; RETAINED_INDEFINITELY) diff --git a/scripts/releng/BuildDropDataGenerator.java b/scripts/releng/BuildDropDataGenerator.java index 48b725d3462..1b6d57fa0bd 100644 --- a/scripts/releng/BuildDropDataGenerator.java +++ b/scripts/releng/BuildDropDataGenerator.java @@ -78,7 +78,7 @@ void mainEclipsePageData() throws IOException { // files buildProperties.add("p2Repository", JSON.Array.create(// - createFileEntry("repository-" + buildId + ".zip", files, "All", "repo.gif"))); + createFileEntry("repository-" + buildId + ".zip", files, "All"))); buildProperties.add("sdkProducts", collectFileEntries(files, filename -> filename.startsWith("eclipse-SDK-") && !OS.isMacTarGZ(filename))); @@ -89,7 +89,7 @@ void mainEclipsePageData() throws IOException { JSON.Array platformProducts = collectFileEntries(files, filename -> filename.startsWith("eclipse-platform-") && !OS.isMacTarGZ(filename)); platformProducts.add(createFileEntry( // Add separate entry for eclipse-platform product p2-repository - "org.eclipse.platform-" + buildId + ".zip", files, "Platform Runtime Repo", "repo.gif")); + "org.eclipse.platform-" + buildId + ".zip", files, "Platform Runtime Repo")); buildProperties.add("platformProducts", platformProducts); buildProperties.add("jdtCompiler", JSON.Array.create( // @@ -200,22 +200,12 @@ JSON.Array colleFilesInDirectory(Path inDirectory, Predicate filenameFil return 100; })).thenComparing(Comparator.naturalOrder()); -JSON.Object createFileEntry(String filename, Map buildFiles, String platform, String icon) { - return createFileEntry(Path.of(filename), buildFiles, platform, icon); -} - JSON.Object createFileEntry(String filename, Map buildFiles, String platform) { - return createFileEntry(Path.of(filename), buildFiles, platform, null); -} - -JSON.Object createFileEntry(Path filename, Map buildFiles, String platform, String icon) { - JSON.Object file = createFileDescription(filename, buildFiles.get(filename)); + Path filePath = Path.of(filename); + JSON.Object file = createFileDescription(filePath, buildFiles.get(filePath)); if (platform != null) { file.add("platform", JSON.String.create(platform)); } - if (icon != null) { - file.add("icon", JSON.String.create(icon)); - } return file; } diff --git a/sites/.gitignore b/sites/.gitignore new file mode 100644 index 00000000000..9021788b1ef --- /dev/null +++ b/sites/.gitignore @@ -0,0 +1,6 @@ +eclipse/**/*.json +equinox/**/*.json +eclipse/build/compilelogs/**/*.xml + +eclipse/build/buildUnstable +equinox/build/buildUnstable diff --git a/sites/eclipse/.gitignore b/sites/eclipse/.gitignore deleted file mode 100644 index 35ad603205a..00000000000 --- a/sites/eclipse/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.json -**/compilelogs/**/*.xml diff --git a/sites/eclipse/build/buildlogs/logs.html b/sites/eclipse/build/buildlogs/logs.html index a8693a297d1..f6b11c0367f 100644 --- a/sites/eclipse/build/buildlogs/logs.html +++ b/sites/eclipse/build/buildlogs/logs.html @@ -25,12 +25,12 @@

Build Properties

Build logs

-
    +

    Comparator Logs

    For explaination, see Platform Build Comparator Logs wiki.

    -
      +

      For an archive of all relevant baseline-versus-current build artifact byte codes download and 'diff' matching files of artifact comparisons. diff --git a/sites/eclipse/build/index.html b/sites/eclipse/build/index.html index 58a04c4554c..5f953f7aae6 100644 --- a/sites/eclipse/build/index.html +++ b/sites/eclipse/build/index.html @@ -18,48 +18,46 @@

      Eclipse ${release} ${buildTypeName} Build: ${label}

      -

      + +
      +

      This page provides access to the various deliverables of Eclipse Platform build along with its logs and tests.

      -

      - New and Noteworthy -
      - Acknowledgments -
      - Eclipse Project ${releaseShort} Readme -
      - Eclipse Project Plan -
      -

      - -

      Logs and Test Links

      -

      Summary of Unit Test Results

      +

      Reports

      - No integration and unit test configurations are complete. + The Reports page provides detailed build and tests logs and analyses of various aspects of this build.

      + +

      Test Results Summary

      - - - - - + + + + +
      Tested PlatformFailedPassedTotalRuntimeTested PlatformFailedPassedTotalRuntime
      -

      Related Links

      +

      Git Log

      + +

      Checksums (SHA 512) and GPG Signatures

      +

      @@ -128,6 +126,8 @@

      SWT Binary and Source return data }) + injectUnstableBuildCause('build-state-container') + contentPostProcessor = (mainElement, build) => { document.title = `${build.label} - ${document.title}` @@ -139,15 +139,13 @@

      SWT Binary and Source const testResultsTable = document.getElementById('tests-overview-table') const tBody = testResultsTable.createTBody() testResultsOverview.then(testResults => { - let completedTests = 0 for (let r = 0; r < testResults.length; r++) { const row = tBody.insertRow() const result = testResults[r] const testName = build.expectedTests[r] - //TODO: compute nicer, non-breaking label (like for file Platforms?) and align elements horizontally - const label = `${testName}` + const [os, ws, arch, javaVersion] = parseTestConfiguration(testName) + const label = `${getOSLabel(os)} (${getCPUArchLabel(arch)}) Java ${javaVersion}` if (result.duration) { // Test configuration completed - completedTests++ row.innerHTML = ` ${label} ${result.failCount} @@ -163,8 +161,6 @@

      SWT Binary and Source ` } } - // Inject test completion state - document.getElementById('test-completion-state').innerHTML = `${completedTests} of ${testResults.length}` }) if (build.signOffIssue) { @@ -189,7 +185,7 @@

      SWT Binary and Source const tBody = table.createTBody() for (const file of filesData) { tBody.insertRow().innerHTML = ` - ${file.icon ? `` : ''} ${file.platform ? file.platform : getPlatformLabel(file.name)} + ${file.platform ? file.platform : getPlatformLabel(file.name)} ${file.name} @@ -206,13 +202,6 @@

      SWT Binary and Source return `${os} (${arch})` } - fetch('buildUnstable').then(res => res.status == 404 ? '' : res.text()).then(msg => { - if (msg) { - const statusLabel = document.getElementById('build-state-container') - statusLabel.innerHTML = 'Unstable!' + msg - } - }) - generate() diff --git a/sites/eclipse/build/repo.gif b/sites/eclipse/build/repo.gif deleted file mode 100644 index b8568f4f812ba932aaa1c9042ffd8fb10c2ba6af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 353 zcmZ?wbhEHb6krfwxXQrrY1PO7d;VXX{@~)w2Q{hPTc)1vNL;nH?R<0Y^o4CZOB36s z*RAa>UAS}hmDT-6tI~QmO+CAM!qMWT4@#FkDqa4lYR&WdP47T*4iQ9wdQLBD_bWhJ*01`Rh2f7L`BX0c&o;Nas_ktf?p71MIz>FDMWmzLJ_Compile issues

      for (const testConfig of build.expectedTests) { const [os, ws, arch, javaVersion] = parseTestConfiguration(testConfig) const headerCell = document.createElement('th'); - headerCell.innerHTML = `${getOSLabel(os)}
      ${getCPUArchLabel(arch)}
      Java ${javaVersion}` + headerCell.innerHTML = `${getOSLabel(os)}
      ${getCPUArchLabel(arch)}
      Java ${javaVersion}` headerCell.style = 'text-align:center' testConfigsHeadline.appendChild(headerCell) expectedTestsLongNames.push(getLongTestConfigurationName(testConfig, build)) diff --git a/sites/eclipse/build/testresults/logs.html b/sites/eclipse/build/testresults/logs.html index fc6e25501d1..eaa7cb4b123 100644 --- a/sites/eclipse/build/testresults/logs.html +++ b/sites/eclipse/build/testresults/logs.html @@ -20,7 +20,7 @@

      Test Console Logs for ${label}

      Console Logs

      These logs contain the console output captured while running the JUnit automated tests.

      -
        +
        @@ -51,11 +51,11 @@

        Console Logs

        let testLogsList = `

        Individual test logs from ${testConfigLong}

        -
          +
            ` let directorLogsList = `

            P2 director logs while installing tests on ${testConfigLong}

            -
              +
                ` for (const testName of tests) { const test = testsSummary[testName] diff --git a/sites/eclipse/page.css b/sites/eclipse/page.css index 9a250694e0f..b9c29859201 100644 --- a/sites/eclipse/page.css +++ b/sites/eclipse/page.css @@ -12,10 +12,6 @@ margin-bottom: 5px; } -#copyright { - padding-left: 0; -} - table { table-layout: fixed; width: 100%; @@ -55,6 +51,38 @@ td { padding: 5px; } +ul { + list-style-type: square; +} + +code { + background-color: lavender; + color: darkslategray; + border-radius: 2px; +} + +/* table of content */ + +li.toc-item { + padding: 3px; + list-style-type: none; +} + +li.toc-item:hover { + background-color: gainsboro; +} + +li.toc-item a { + /*Supress styling of links in TOC items*/ + color: inherit; + text-decoration: none; +} + +.error-message-box { + background-color: #ffdddd; + border-left: 6px solid crimson; + padding: 5px; +} /* Collapsibles/accordion tables */ .collapsible-table-main-row { @@ -69,7 +97,7 @@ td { .collapsible-table-animation-wrapper { display: grid; grid-template-rows: 0fr; - transition: grid-template-rows 0.3s ease-out; + transition: grid-template-rows 0.5s ease-out; } /*Use a grid wrapper to transition from 0fr (closed) to 1fr (open).*/ diff --git a/sites/eclipse/page.js b/sites/eclipse/page.js index 8a31f8b5976..a331d1dc4d3 100644 --- a/sites/eclipse/page.js +++ b/sites/eclipse/page.js @@ -78,16 +78,18 @@ function getOSLabel(name) { throw new Error('Cannot determine OS from name: ' + name) } } -//TODO: make entire labels non-breaking + function getCPUArchLabel(name) { + // Use non-breaking space and hypen in label + const bit64 = '64‑bit' if (name.includes('x86_64')) { - return 'x86 64-bit' + return `x86 ${bit64}` } else if (name.includes('aarch64')) { - return 'ARM 64-bit' + return `ARM ${bit64}` } else if (name.includes('ppc64le')) { - return 'PowerPC 64-bit' + return `PowerPC ${bit64}` } else if (name.includes('riscv64')) { - return 'RISC-V 64-bit' + return `RISC‑V ${bit64}` } else { throw new Error('Cannot determine CPU-Arch from name: ' + name) } @@ -180,49 +182,34 @@ function formatBuildDate(date) { return BUILD_DATE_FORMAT.format(new Date(date)) } -// Cache the runtime formatter if the API is available -let runtimeFormat = null; -if (typeof Intl.DurationFormat !== 'undefined') { - try { - runtimeFormat = new Intl.DurationFormat('en', { style: 'short' }); - } catch (e) { - // Intl.DurationFormat not available - } -} - function formatRuntime(runtime) { const totalSeconds = Math.trunc(runtime); - - // Try to use Temporal API if both Temporal and DurationFormat are available (not supported in all browsers yet) - if (typeof Temporal !== 'undefined' && Temporal.Duration && runtimeFormat) { - try { - const duration = Temporal.Duration.from({ seconds: totalSeconds }); - return runtimeFormat.format(duration.round({ - largestUnit: 'hours', - smallestUnit: totalSeconds >= 3600 ? 'minutes' : 'seconds' - })); - } catch (e) { - // Fall through to fallback implementation - } - } - - // Fallback implementation for browsers without Temporal/DurationFormat support - const hours = Math.floor(totalSeconds / 3600); - const minutes = Math.floor((totalSeconds % 3600) / 60); - const seconds = totalSeconds % 60; - + // Not all browsers support the Intl.DurationFormat and Temporal.Duration API... so do it 'manually' + const hours = Math.floor(totalSeconds / 3600) + const minutes = Math.floor((totalSeconds % 3600) / 60).toString().padStart(2, '0') + const seconds = (totalSeconds % 60).toString().padStart(2, '0') if (hours > 0) { // For durations >= 1 hour, show hours and minutes - return `${hours} hr, ${minutes} min`; + return `${hours} hr, ${minutes} min`; } else if (minutes > 0) { // For durations < 1 hour but >= 1 minute, show minutes and seconds - return `${minutes} min, ${seconds} sec`; + return `${minutes} min, ${seconds} sec`; } else { // For durations < 1 minute, show only seconds - return `${seconds} sec`; + return `${seconds} sec`; } } +function injectUnstableBuildCause(buildStateContainerId) { + fetch('buildUnstable').then(res => res.status == 404 ? '' : res.text()).then(msg => { + if (msg) { + const statusContainer = document.getElementById(buildStateContainerId) + statusContainer.classList.add('error-message-box') + statusContainer.innerHTML = `UNSTABLE
                ${msg}` + } + }) +} + function fetchAllJSON(urls) { const promises = urls.map(url => fetch(url).then(res => { if (res.status == 404) { @@ -288,17 +275,37 @@ function generate() { } } +const tocLevelIndentation = '0px' + function generateTOCItems(mainElement) { const headersOfTOC = mainElement.querySelectorAll('h1[id], h2[id], h3[id], h4[id]'); if (headersOfTOC.length === 0) { document.getElementById('toc-container').remove() } else { - //TODO: Consider to use the more advanced style from the large aside at https://eclipse.dev/eclipse/news/news.html const tocList = document.getElementById('table-of-contents') + tocList.style.marginLeft = tocLevelIndentation + + let lastLevel = -1; + const lists = [tocList]; for (const header of headersOfTOC) { const item = document.createElement('li') + item.classList.add('toc-item') item.innerHTML = `${header.textContent}` - tocList.appendChild(item) + + const level = parseInt(header.tagName.substring(1)); + if (lastLevel < 0) { + lastLevel = level + } + if (level > lastLevel) { + const newList = document.createElement('ul'); + newList.style.marginLeft = tocLevelIndentation + lists[lists.length - 1].appendChild(newList); + lists.push(newList); + } else if (level < lastLevel) { + lists.pop(); + } + lists[lists.length - 1].appendChild(item); + lastLevel = level; } } } @@ -348,7 +355,7 @@ function verifyDataConsistency(preliminaryData, data) { } function logException(message, loggedObject) { - document.body.prepend(toElement(`

                Failed to generate content: ${message}

                `)); + document.body.prepend(toElement(`

                Failed to generate content: ${message}

                `)); console.log(loggedObject); } @@ -377,9 +384,9 @@ function generateBody() {