This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris-website.git


The following commit(s) were added to refs/heads/master by this push:
     new 5e9ed7644189 [improvement](website) Avoid discarded Git dates and 
repeated HTML parsing (#4538)
5e9ed7644189 is described below

commit 5e9ed76441890c1096e7c562746d00702e93f038
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Wed Oct 28 03:43:39 2026 +0000

    [improvement](website) Avoid discarded Git dates and repeated HTML parsing 
(#4538)
    
    The complete five-language production build now has healthy memory
    headroom, but run 40608604747 took 143:30 for the build job, exceeding
    the existing 180-minute budget with 30% margin. Its managed docs
    repeatedly ask Git for dates of generated, untracked translation views,
    then discard those dates in favor of actual source dates; strict
    verification also reparses pages already visited as counterparts.
    
    Suppress native date/author lookup only while loading a managed
    translation view, restore the original options before contentLoaded, and
    retain the existing per-document source-date restoration. Real source
    lookups and displayed date/author options remain intact. Reuse the same
    invocation's compact immutable HTML metadata for each page's own
    assertions as well as counterpart checks. Keep every language, status,
    canonical, robots, heading, sitemap, search-exclusion and
    reciprocal-alternate assertion, including duplicate canonicals without
    href.
    
    Validation:
    - 408 local Node checks: 406 passed, 2 conditional skips; 27 workflow
    checks passed.
    - Same-source real five-language fixture: all 230 files / 3,294,801
    bytes identical before and after the date change; generated-view Git
    lookups decreased from 36 to zero.
    - New native fixture verifies source date/author and visible footer
    options on 40 source, translated and fallback pages; it runs in the
    existing content-fixture CI path and its own changes select that path.
    - Existing five-language content fixture returns identical strict
    results in before/after/after/before comparisons; full HTML parses
    decrease from 51 to 41. Negative cases still reject damaged headings,
    duplicate alternates, wrong body language/status, duplicate canonicals
    without href, and indexed-page noindex.
    
    These are fixture results, not a claim that the complete production time
    budget has passed. T22 remains open until a new complete production run
    and public acceptance succeed. No local full website build was
    performed.
    
    | Repository review checkpoint | Conclusion |
    | --- | --- |
    | Goal | Removes measured discarded work without changing source-date
    policy or reducing checks; final production budget remains to be
    measured. |
    | Focus | Only managed date loading, immutable verifier summaries and
    their regression/CI coverage change. |
    | Information architecture / locales / versions | No content, state,
    ownership, versions, sidebars or coverage denominators change. |
    | URLs / anchors / navigation | Routes and anchors are unchanged;
    heading and reciprocal-link assertions remain. |
    | Frontend / mobile / SSR / themes | No frontend or styling change;
    date/author footers and same-source output bytes are verified. |
    | Validation | Real five-language builds, negative cases, CI selection
    and existing Node/workflow checks cover the changes; production timing
    will follow. |
    | Other quality | No dependency, credential, permission or
    publication-boundary changes. Existing content link debt remains
    separately registered in T23. |
    
    Co-authored-by: morningman <[email protected]>
---
 .github/workflows/build-check.yml            |  1 +
 scripts/i18n/__tests__/ci-sampling.test.cjs  |  3 ++
 scripts/i18n/__tests__/static-cache.test.cjs | 13 +++++++
 scripts/i18n/ci-plan.cjs                     |  2 +-
 scripts/i18n/docs-plugin.cjs                 | 10 ++++-
 scripts/i18n/verify-doc-dates-fixture.cjs    | 56 ++++++++++++++++++++++++++++
 scripts/i18n/verify-static.cjs               | 47 +++++++++++------------
 7 files changed, 107 insertions(+), 25 deletions(-)

diff --git a/.github/workflows/build-check.yml 
b/.github/workflows/build-check.yml
index a9873df6e599..3ade1b45f782 100644
--- a/.github/workflows/build-check.yml
+++ b/.github/workflows/build-check.yml
@@ -140,6 +140,7 @@ jobs:
               if: steps.detect.outputs.content_fixture == 'true'
               run: |
                   node scripts/i18n/verify-content-fixture.cjs
+                  node scripts/i18n/verify-doc-dates-fixture.cjs
                   node scripts/i18n/verify-blog-fixture.cjs
                   node scripts/i18n/verify-release-policy-fixture.cjs
 
diff --git a/scripts/i18n/__tests__/ci-sampling.test.cjs 
b/scripts/i18n/__tests__/ci-sampling.test.cjs
index 73695721b86e..e9476784c3b9 100644
--- a/scripts/i18n/__tests__/ci-sampling.test.cjs
+++ b/scripts/i18n/__tests__/ci-sampling.test.cjs
@@ -95,6 +95,9 @@ test('CI tooling only runs the fixtures for its own 
subsystem', () => {
     assert.equal(language.runContentFixture, true);
     assert.equal(language.runSamplingFixture, false);
     assert.equal(language.runPublishFixture, false);
+    const dates=policy(['scripts/i18n/verify-doc-dates-fixture.cjs']);
+    
assert.equal(dates.mode,'fixtures');assert.equal(dates.runContentFixture,true);
+    assert.equal(dates.publicationAllowed,false);
     const sampler = policy(['scripts/i18n/ci-sample.cjs']);
     assert.equal(sampler.runSamplingFixture, true);
     assert.equal(sampler.runPublishFixture, false);
diff --git a/scripts/i18n/__tests__/static-cache.test.cjs 
b/scripts/i18n/__tests__/static-cache.test.cjs
index b0456e1068e5..fe41260f015c 100644
--- a/scripts/i18n/__tests__/static-cache.test.cjs
+++ b/scripts/i18n/__tests__/static-cache.test.cjs
@@ -39,3 +39,16 @@ test('each invocation rereads the artifact and rejects 
damaged heading IDs and d
     const 
$=cheerio.load(original);$('head').append($('link[hreflang="ko"]').clone());fs.writeFileSync(file,$.html());
     assert.throws(()=>verifyAll(data),/Duplicate hreflang/);
 });
+
+test('cached counterpart metadata still rejects each page own language, 
notice, canonical and robots defects',t=>{
+    const 
data=fixture(t),file=path.join(data.site,'ko/topic/index.html'),original=fs.readFileSync(file,'utf8');
+    for(const [change,message]of [
+        [text=>text.replace('lang="ko"><h2','lang="en"><h2'),/Body language/],
+        
[text=>text.replace('data-translation-status="current"','data-translation-status="wrong"'),/Notice/],
+        [text=>text.replace('</head>','<link 
rel="canonical"></head>'),/Duplicate canonical/],
+        [text=>text.replace('</head>','<meta name="robots" 
content="noindex"></head>'),/ko\/topic/],
+    ]){
+        fs.writeFileSync(file,change(original));
+        assert.throws(()=>verifyAll(data),message);
+    }
+});
diff --git a/scripts/i18n/ci-plan.cjs b/scripts/i18n/ci-plan.cjs
index b02eae80433c..ff99e7a6695c 100644
--- a/scripts/i18n/ci-plan.cjs
+++ b/scripts/i18n/ci-plan.cjs
@@ -65,7 +65,7 @@ function policy(files, {forceFull = false, forceSample = 
false} = {}) {
         runContentFixture:
             (shared && checks.check_content_fixture) ||
             files.some(file =>
-                
/verify-(content-fixture|global-language)|__tests__\/fixtures\/content-manifest/.test(file),
+                
/verify-(content-fixture|doc-dates-fixture|global-language)|__tests__\/fixtures\/content-manifest/.test(file),
             ),
         runSamplingFixture: files.some(file =>
             
/^scripts\/(build-locales?\.cjs$|i18n\/(compiler-processes|ci-sample|ci-blog-sample|build-cache|verify-ci-sampl(?:e|ing-fixture))\.cjs$)/.test(file)),
diff --git a/scripts/i18n/docs-plugin.cjs b/scripts/i18n/docs-plugin.cjs
index 057a6751e15c..4b6dc94b03e1 100644
--- a/scripts/i18n/docs-plugin.cjs
+++ b/scripts/i18n/docs-plugin.cjs
@@ -208,7 +208,15 @@ module.exports = async function 
translationDocsPlugin(context, options) {
             // the view, just like a new static build. Do not watch our own 
view.
             if (loaded) return (await translationDocsPlugin(context, 
options)).loadContent();
             loaded = true;
-            const content = await plugin.loadContent();
+            let content;
+            const dateOptions = {showLastUpdateTime: 
options.showLastUpdateTime,
+                showLastUpdateAuthor: options.showLastUpdateAuthor};
+            // Native dates for generated views would query untracked files.
+            // Every managed doc receives its actual source dates below. Keep
+            // the original options for contentLoaded and the displayed footer.
+            if (activeLocale) Object.assign(options, {showLastUpdateTime: 
false, showLastUpdateAuthor: false});
+            try {content = await plugin.loadContent();}
+            finally {if (activeLocale) Object.assign(options, dateOptions);}
             if (activeLocale) {
                 for (const version of content.loadedVersions) {
                     for (const doc of [...version.docs, ...version.drafts]) {
diff --git a/scripts/i18n/verify-doc-dates-fixture.cjs 
b/scripts/i18n/verify-doc-dates-fixture.cjs
new file mode 100644
index 000000000000..2da72bb4cb91
--- /dev/null
+++ b/scripts/i18n/verify-doc-dates-fixture.cjs
@@ -0,0 +1,56 @@
+// Real native docs dates and footer checks, including untracked translation 
views.
+const 
fs=require('node:fs'),path=require('node:path'),assert=require('node:assert/strict');
+const {spawnSync,execFileSync}=require('node:child_process');
+const cheerio=require('cheerio');
+const {createFixture}=require('./__tests__/fixtures/multi-locale.cjs');
+const {hash}=require('./state.cjs');
+const 
root=path.resolve(__dirname,'../..'),fixture=path.join(root,'.i18n-build/date-fixture');
+async function main(){
+    fs.rmSync(fixture,{recursive:true,force:true});
+    await createFixture(fixture);
+    for(const locale of ['ja','ko','ru']){
+        const 
file=path.join(fixture,'translations/state',locale,'docs.json'),state=JSON.parse(fs.readFileSync(file));
+        for(const record of state.pages){
+            const 
target=path.join(fixture,record.targetPath),content=fs.readFileSync(target,'utf8').replace(/last_update:\n
  date: 2026-01-01\n/,'');
+            fs.writeFileSync(target,content);record.targetHash=hash(content);
+        }
+        fs.writeFileSync(file,JSON.stringify(state));
+    }
+    fs.appendFileSync(path.join(fixture,'docusaurus.config.js'),`\nconst 
original=module.exports;module.exports=()=>{const config=original();
+for(const item of 
config.plugins)if(Array.isArray(item)&&item[1]?.path){item[1].showLastUpdateTime=true;item[1].showLastUpdateAuthor=true;}
+return config;};\n`);
+    execFileSync('git',['add','.'],{cwd:fixture});
+    
execFileSync('git',['-c','user.name=Fixture','-c','[email protected]','commit','-qm','Source
 date fixture'],{cwd:fixture});
+    const 
directory=path.join(root,'.i18n-build/date-git-calls'),probe=path.join(root,'.i18n-build/date-git-probe.cjs');
+    
fs.rmSync(directory,{recursive:true,force:true});fs.mkdirSync(directory,{recursive:true});
+    fs.writeFileSync(probe,`const 
fs=require('node:fs'),path=require('node:path');
+const 
utils=require(${JSON.stringify(require.resolve('@docusaurus/utils/lib/gitUtils.js'))}),original=utils.getFileCommitDate,paths=[];
+utils.getFileCommitDate=function(file,...args){paths.push(file);return 
original(file,...args);};
+process.on('exit',()=>{fs.writeFileSync(path.join(process.env.DORIS_DATE_PROBE_DIRECTORY,process.pid+'.json'),JSON.stringify({paths}));});\n`);
+    const 
result=spawnSync(process.execPath,[path.join(root,'scripts/build-locales.cjs'),'--site-dir',fixture],{
+        
cwd:root,stdio:'inherit',env:{...process.env,NODE_OPTIONS:`--max-old-space-size=4096
 --require ${JSON.stringify(probe)}`,
+            DORIS_DATE_PROBE_DIRECTORY:directory}});
+    assert.equal(result.status,0,'Source date five-language native build');
+    const 
calls=fs.readdirSync(directory).flatMap(file=>JSON.parse(fs.readFileSync(path.join(directory,file))).paths);
+    const 
viewCalls=calls.filter(file=>/[/\\]\.i18n-build[/\\](ja|ko|ru)[/\\]docusaurus-plugin-content-docs/.test(file));
+    assert.equal(viewCalls.length,0,'Generated translation views must never 
query Git dates');
+    assert(calls.length>0,'Real source author dates must still use native Git 
lookup when required');
+    const checked=[];
+    for(const locale of ['en','zh-CN','ja','ko','ru']){
+        const 
manifest=JSON.parse(fs.readFileSync(path.join(fixture,'.i18n-build/content-manifests',locale+'.json')));
+        for(const page of manifest.pages.filter(page=>page.kind==='docs')){
+            const 
$=cheerio.load(fs.readFileSync(path.join(fixture,'build',page.route,'index.html'),'utf8')),footer=$('.theme-last-updated');
+            assert.equal(footer.length,1,`Date footer options must remain 
enabled: ${page.route}`);
+            
assert.equal(footer.find('time').attr('datetime'),'2026-01-01T00:00:00.000Z',page.route);
+            assert(footer.text().includes('Fixture'),`Source author: 
${page.route}`);
+            
checked.push({locale,route:page.route,contentLocale:page.contentLocale,sourceDate:'2026-01-01',sourceAuthor:'Fixture'});
+        }
+    }
+    const 
report={passed:true,implementationSha:execFileSync('git',['rev-parse','HEAD'],{cwd:root,encoding:'utf8'}).trim(),
+        
fixtureSourceSha:execFileSync('git',['rev-parse','HEAD'],{cwd:fixture,encoding:'utf8'}).trim(),
+        temporaryViewGitCalls:0,sourceGitCalls:calls.length,checked,
+        scope:'Real five-language native docs build; source date/author and 
visible footer options retained for source, translated and fallback pages. No 
full website build.'};
+    
fs.writeFileSync(path.join(root,'.i18n-build/doc-dates-fixture-verification.json'),JSON.stringify(report,null,2)+'\n');
+    
console.log(JSON.stringify({passed:true,temporaryViewGitCalls:0,sourceGitCalls:calls.length,checked:checked.length}));
+}
+if(require.main===module)main().catch(error=>{console.error(error);process.exitCode=1;});
diff --git a/scripts/i18n/verify-static.cjs b/scripts/i18n/verify-static.cjs
index 68389918b403..d20c124b6d29 100644
--- a/scripts/i18n/verify-static.cjs
+++ b/scripts/i18n/verify-static.cjs
@@ -52,7 +52,12 @@ function verify({site, manifest, partial = false, headCache 
= new Map()}) {
                 if (!alternates.has(lang)) alternates.set(lang, []);
                 alternates.get(lang).push($(node).attr('href'));
             }
-            headCache.set(file, {headingIds:headingIds($), alternates});
+            headCache.set(file, {headingIds:headingIds($), alternates,
+                htmlLang:$('html').attr('lang'), 
bodyLang:$('.theme-doc-markdown,.course-doc-content').attr('lang'),
+                
translationStatus:$('[data-translation-status]').attr('data-translation-status'),
+                
canonicals:$('link[rel="canonical"]').toArray().map(node=>$(node).attr('href')),
+                robots:$('meta[name="robots"]').attr('content'),
+                ogUrl:$('meta[property="og:url"]').attr('content'), 
ogLocale:$('meta[property="og:locale"]').attr('content')});
         }
         return headCache.get(file);
     }
@@ -71,19 +76,15 @@ function verify({site, manifest, partial = false, headCache 
= new Map()}) {
             assert(page.draft, `Missing non-draft static page: 
${page.permalink}`);
             continue;
         }
-        const $ = cheerio.load(fs.readFileSync(filename, 'utf8'));
-        head(filename, $);
-        const body = $('.theme-doc-markdown,.course-doc-content');
-        assert.equal(body.attr('lang'), page.contentLocale, `Body language: 
${page.permalink}`);
-        
assert.equal($('[data-translation-status]').attr('data-translation-status'), 
page.status, `Notice: ${page.permalink}`);
-        assert.equal($('link[rel="canonical"]').length, 1, `Duplicate 
canonical: ${page.permalink}`);
+        const metadata = head(filename);
+        assert.equal(metadata.bodyLang, page.contentLocale, `Body language: 
${page.permalink}`);
+        assert.equal(metadata.translationStatus, page.status, `Notice: 
${page.permalink}`);
+        assert.equal(metadata.canonicals.length, 1, `Duplicate canonical: 
${page.permalink}`);
         const canonical = page.useTarget ? page.permalink : page.contentLocale 
=== 'en' ? page.englishPermalink : page.sourcePermalink;
-        assert.equal($('link[rel="canonical"]').attr('href'), 
`https://doris.apache.org${canonical}`);
-        const alternates = $('link[rel="alternate"][hreflang]');
-        const localized = alternates.filter(`[hreflang="${htmlLang}"]`);
-        assert.equal(localized.length, alternateGroup[locale] ? 1 : 0, 
`Localized alternate: ${page.permalink}`);
+        assert.equal(metadata.canonicals[0], 
`https://doris.apache.org${canonical}`);
+        assert.equal(metadata.alternates.get(htmlLang)?.length ?? 0, 
alternateGroup[locale] ? 1 : 0, `Localized alternate: ${page.permalink}`);
         if (!page.indexable) {
-            
assert($('meta[name="robots"]').attr('content').includes('noindex'), 
page.permalink);
+            assert(metadata.robots.includes('noindex'), page.permalink);
             assert(!sitemapPaths.has(page.permalink), `Fallback/stale page in 
sitemap: ${page.permalink}`);
             assert(!indexedPaths.has(page.permalink), `Fallback/stale page in 
local search index: ${page.permalink}`);
             for (const permalink of Object.values(alternateGroup)) {
@@ -94,10 +95,10 @@ function verify({site, manifest, partial = false, headCache 
= new Map()}) {
                 }
             }
         } else {
-            assert(!($('meta[name="robots"]').attr('content') ?? 
'').includes('noindex'), page.permalink);
+            assert(!(metadata.robots ?? '').includes('noindex'), 
page.permalink);
             assert(sitemapPaths.has(page.permalink), `Current page missing 
from sitemap: ${page.permalink}`);
             const english = counterpart(page.englishPermalink, 'source heading 
IDs');
-            if (english) assert.deepEqual(headingIds($), english.headingIds, 
`Source heading IDs: ${page.permalink}`);
+            if (english) assert.deepEqual(metadata.headingIds, 
english.headingIds, `Source heading IDs: ${page.permalink}`);
             for (const [lang, permalink] of Object.entries(alternateGroup)) {
                 const counterpart$ = counterpart(permalink, 'reciprocal 
alternates');
                 if (!counterpart$) continue;
@@ -117,20 +118,20 @@ function verify({site, manifest, partial = false, 
headCache = new Map()}) {
     for (const permalink of data.pageRoutes ?? []) {
         const filename = path.join(site, decodeURIComponent(permalink), 
'index.html');
         assert(fs.existsSync(filename), `Missing ordinary page: ${permalink}`);
-        const $ = cheerio.load(fs.readFileSync(filename, 'utf8'));
+        const metadata = head(filename);
         const source = permalink.startsWith(`/${locale}/`) ? 
permalink.slice(locale.length + 1) : permalink;
         const translatedPages = data.translatedPagePaths?.[locale] ?? 
record?.translatedPages;
         const decision = contentByRoute.get(permalink);
         const fallback = decision ? decision.fallback : record?.ordinaryPages 
=== false && !translatedPages?.includes(source.replace(/\/+$/, ''));
         if (fallback) {
-            assert.equal($('html').attr('lang'), htmlLang, `Fallback 
navigation language: ${permalink}`);
-            assert.equal($('link[rel="canonical"]').length, 1, `Duplicate 
ordinary canonical: ${permalink}`);
-            assert.equal($('link[rel="canonical"]').attr('href'), 
`https://doris.apache.org${source}`);
-            assert.equal($('meta[property="og:url"]').attr('content'), 
`https://doris.apache.org${source}`);
-            assert.equal($('meta[property="og:locale"]').attr('content'), 
'en_US');
-            assert(($('meta[name="robots"]').attr('content') ?? 
'').includes('noindex'), `Indexed English fallback: ${permalink}`);
+            assert.equal(metadata.htmlLang, htmlLang, `Fallback navigation 
language: ${permalink}`);
+            assert.equal(metadata.canonicals.length, 1, `Duplicate ordinary 
canonical: ${permalink}`);
+            assert.equal(metadata.canonicals[0], 
`https://doris.apache.org${source}`);
+            assert.equal(metadata.ogUrl, `https://doris.apache.org${source}`);
+            assert.equal(metadata.ogLocale, 'en_US');
+            assert((metadata.robots ?? '').includes('noindex'), `Indexed 
English fallback: ${permalink}`);
             assert(!sitemapPaths.has(permalink), `Ordinary fallback in 
sitemap: ${permalink}`);
-            
assert.equal($(`link[rel="alternate"][hreflang="${htmlLang}"]`).length, 0, 
`Ordinary fallback alternate: ${permalink}`);
+            assert.equal(metadata.alternates.get(htmlLang)?.length ?? 0, 0, 
`Ordinary fallback alternate: ${permalink}`);
             for (const sourceRoute of (decision ? 
Object.values(decision.navigationRoutes) : [source, `/zh-CN${source}`])) {
                 const source$ = counterpart(sourceRoute, 'ordinary fallback 
alternates');
                 if (source$) 
assert.equal(source$.alternates.get(htmlLang)?.length ?? 0, 0,
@@ -138,7 +139,7 @@ function verify({site, manifest, partial = false, headCache 
= new Map()}) {
             }
             ordinaryPages.fallback++;
         } else {
-            assert.equal($('html').attr('lang'), htmlLang, `Translated 
ordinary page language: ${permalink}`);
+            assert.equal(metadata.htmlLang, htmlLang, `Translated ordinary 
page language: ${permalink}`);
         }
         ordinaryPages.verified++;
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to