From 8391f826fe3fa08f906e8be4d1b26033426c5b6a Mon Sep 17 00:00:00 2001 From: pavlov346346-source Date: Wed, 9 Sep 2026 02:34:25 +0300 Subject: [PATCH] Fix v17.7.1 release workflow --- .github/workflows/release-v17-7-1.yml | 251 ++------------------------ 1 file changed, 14 insertions(+), 237 deletions(-) diff --git a/.github/workflows/release-v17-7-1.yml b/.github/workflows/release-v17-7-1.yml index 035d9a8..95e61c8 100644 --- a/.github/workflows/release-v17-7-1.yml +++ b/.github/workflows/release-v17-7-1.yml @@ -1,7 +1,8 @@ name: Caterium v17.7.1 data layer adoption on: push: - branches: [main] + branches: + - main paths: - '.github/workflows/release-v17-7-1.yml' permissions: @@ -13,242 +14,18 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 22 - - name: Apply v17.7.1 patch - shell: bash + node-version: '22' + - name: Apply patch + run: python ops/release_v1771.py + - name: Install dependencies + run: npm install + - name: Validate release + run: npm run check:deploy + - name: Commit release run: | - python - <<'PY' - from pathlib import Path - import json - - ROOT=Path('.') - OLD_RELEASE='20260908-v17-7-0-architecture-foundation' - NEW_RELEASE='20260909-v17-7-1-data-layer-adoption' - OLD_CACHE='v75-20260908-v17-7-0-architecture-foundation' - NEW_CACHE='v76-20260909-v17-7-1-data-layer-adoption' - - def read(path): return (ROOT/path).read_text(encoding='utf-8') - def write(path,text): - p=ROOT/path;p.parent.mkdir(parents=True,exist_ok=True);p.write_text(text,encoding='utf-8') - def repl(path,old,new,count=None): - text=read(path);n=text.count(old) - if n==0: raise SystemExit(f'marker not found in {path}: {old[:100]}') - if count is not None and n!=count: raise SystemExit(f'unexpected marker count in {path}: {n} != {count}') - write(path,text.replace(old,new)) - - data_layer=r'''(()=>{ - 'use strict'; - if(window.CateriumDataV1771)return; - - const VERSION='17.7.1'; - const RELEASE='20260909-v17-7-1-data-layer-adoption'; - const listeners=new Map(); - const clone=value=>{try{return structuredClone(value)}catch(_){return JSON.parse(JSON.stringify(value))}}; - const safeJson=(raw,fallback)=>{try{const value=JSON.parse(raw);return value==null?fallback:value}catch(_){return fallback}}; - const emit=(topic,payload)=>{for(const fn of listeners.get(topic)||[]){try{fn(payload)}catch(error){console.error('[Caterium Data]',error)}}}; - const subscribe=(topic,fn)=>{if(typeof fn!=='function')return()=>{};if(!listeners.has(topic))listeners.set(topic,new Set());listeners.get(topic).add(fn);return()=>listeners.get(topic)?.delete(fn)}; - - function runtimeOrders(){try{if(typeof orders!=='undefined'&&Array.isArray(orders))return orders}catch(_){}return null} - function runtimeCatalog(){try{if(typeof boxes!=='undefined'&&Array.isArray(boxes))return boxes}catch(_){}return null} - function runtimePersist(){try{return typeof persist==='function'?persist:null}catch(_){return null}} - function cloud(){return window.SunCloudV2||null} - function session(){try{return cloud()?.getSession?.()||null}catch(_){return null}} - function workspace(){try{return cloud()?.getWorkspace?.()||null}catch(_){return null}} - function supportMode(){try{return cloud()?.getSupportMode?.()||null}catch(_){return null}} - function isSignedIn(){return Boolean(session()?.user)} - function isSupportReadOnly(){return Boolean(supportMode()||cloud()?.isSupportMode?.())} - function canWrite(permission='app.write'){ - if(isSupportReadOnly())return false; - if(!isSignedIn())return true; - try{const c=cloud();if(typeof c?.hasPermission==='function')return c.hasPermission(permission)||c.hasPermission('app.write')}catch(_){} - return true; - } - - const storage={ - read(key,fallback=null){const raw=localStorage.getItem(String(key));if(raw==null)return fallback;return safeJson(raw,fallback)}, - write(key,value,{silent=false}={}){localStorage.setItem(String(key),JSON.stringify(value));if(!silent)emit(`storage:${key}`,clone(value));return value}, - remove(key){localStorage.removeItem(String(key));emit(`storage:${key}`,null)}, - raw(key){return localStorage.getItem(String(key))} - }; - - function persistDomain(key,list,persistLocal){ - if(!persistLocal){storage.write(key,list,{silent:true});return} - const p=runtimePersist(); - if(p){try{p();return}catch(error){console.warn('[Caterium Data] persist fallback',error)}} - storage.write(key,list,{silent:true}); - } - - function getOrders(){const live=runtimeOrders();return clone(live||storage.read('sunOrders',[])||[])} - function replaceOrders(next,{persistLocal=true,reason='replace'}={}){ - const list=Array.isArray(next)?clone(next):[];const live=runtimeOrders(); - if(live){live.length=0;live.push(...clone(list))} - persistDomain('sunOrders',list,persistLocal);emit('orders',{reason,orders:clone(list)});return list; - } - function getOrder(id){return getOrders().find(o=>String(o?.id)===String(id))||null} - function updateOrder(id,updater,{persistLocal=true,reason='update'}={}){ - const list=getOrders(),index=list.findIndex(o=>String(o?.id)===String(id));if(index<0)return null; - const current=clone(list[index]),next=typeof updater==='function'?updater(current):{...current,...clone(updater||{})};if(!next)return null; - list[index]=next;replaceOrders(list,{persistLocal,reason});return clone(next); - } - function applyServerOrders(changed,{reason='server'}={}){ - const patches=Array.isArray(changed)?changed:[];if(!patches.length)return {changed:0,ids:[]}; - const list=getOrders(),map=new Map(list.map((o,i)=>[String(o?.id),i])),ids=[]; - for(const patch of patches){const id=String(patch?.id??'');if(!id)continue;const index=map.get(id);if(index==null){list.push(clone(patch));map.set(id,list.length-1)}else list[index]=clone(patch);ids.push(id)} - replaceOrders(list,{persistLocal:false,reason}); - try{window.render?.();window.renderOrders?.();window.renderStats?.();window.renderClients?.()}catch(_){} - try{window.dispatchEvent(new CustomEvent('caterium:data-orders-applied',{detail:{ids,reason}}))}catch(_){} - return {changed:ids.length,ids}; - } - - function getCatalog(){const live=runtimeCatalog();return clone(live||storage.read('sunBoxes',[])||[])} - function replaceCatalog(next,{persistLocal=true,reason='replace'}={}){ - const list=Array.isArray(next)?clone(next):[];const live=runtimeCatalog(); - if(live){live.length=0;live.push(...clone(list))} - persistDomain('sunBoxes',list,persistLocal);emit('catalog',{reason,items:clone(list)});return list; - } - function getCatalogItem(id){return getCatalog().find(x=>String(x?.id)===String(id))||null} - function upsertCatalogItem(item,{persistLocal=true,reason='upsert'}={}){ - if(!item?.id)return null;const list=getCatalog(),index=list.findIndex(x=>String(x?.id)===String(item.id)),next=clone(item); - if(index<0)list.push(next);else list[index]=next;replaceCatalog(list,{persistLocal,reason});return clone(next); - } - function removeCatalogItem(id,{persistLocal=true,reason='remove'}={}){ - const list=getCatalog(),next=list.filter(x=>String(x?.id)!==String(id));if(next.length===list.length)return false; - replaceCatalog(next,{persistLocal,reason});return true; - } - - const ordersRepo={list:getOrders,get:getOrder,replace:replaceOrders,update:updateOrder,applyServerChanges:applyServerOrders}; - const catalogRepo={list:getCatalog,get:getCatalogItem,replace:replaceCatalog,upsert:upsertCatalogItem,remove:removeCatalogItem}; - const diagnostics={ - snapshot(){return {version:VERSION,workspaceId:workspace()?.id||null,signedIn:isSignedIn(),supportReadOnly:isSupportReadOnly(),orderCount:getOrders().length,catalogCount:getCatalog().length,listenerTopics:listeners.size}}, - measure(name,fn){const started=performance.now();return Promise.resolve().then(fn).finally(()=>emit('metric',{name,durationMs:Math.round((performance.now()-started)*10)/10,at:new Date().toISOString()}))} - }; - - const api={VERSION,RELEASE,storage,orders:ordersRepo,catalog:catalogRepo,subscribe,emit,cloud,session,workspace,isSignedIn,isSupportReadOnly,canWrite,diagnostics}; - window.CateriumDataV1771=api; - window.CateriumDataV1770=api; - window.CateriumData=api; - try{window.dispatchEvent(new CustomEvent('caterium:data-ready',{detail:{version:VERSION,phase:2}}))}catch(_){} - })(); - ''' - write('public/core/data-layer-v1771.js',data_layer) - - # Route the base legacy CRUD paths through the data layer while preserving persist() as fallback. - legacy=read('public/legacy/bootstrap.js') - old="function persist(){localStorage.sunBoxes=JSON.stringify(boxes);localStorage.sunOrders=JSON.stringify(orders)}function show(id,b)" - new="function persist(){localStorage.sunBoxes=JSON.stringify(boxes);localStorage.sunOrders=JSON.stringify(orders)}function dataLayer(){return window.CateriumDataV1771||window.CateriumData||window.CateriumDataV1770||null}function persistOrders(reason){let d=dataLayer();if(d?.orders?.replace){d.orders.replace(orders,{persistLocal:true,reason:reason||'legacy.orders'});return}persist()}function persistCatalog(reason){let d=dataLayer();if(d?.catalog?.replace){d.catalog.replace(boxes,{persistLocal:true,reason:reason||'legacy.catalog'});return}persist()}function show(id,b)" - if old not in legacy: raise SystemExit('legacy persist marker missing') - legacy=legacy.replace(old,new,1) - replacements=[ - ("persist();deleteOrderBtn.style.display='inline-block';renderOrders();updateOrderSummary();alert('Заказ сохранён.');","persistOrders('order.save');deleteOrderBtn.style.display='inline-block';renderOrders();updateOrderSummary();alert('Заказ сохранён.');"), - ("function status(id,s){orders.find(x=>x.id==id).status=s;persist()}","function status(id,s){orders.find(x=>x.id==id).status=s;persistOrders('order.status')}"), - ("orders=orders.filter(x=>x.id!=id);persist();renderOrders();","orders=orders.filter(x=>x.id!=id);persistOrders('order.delete');renderOrders();"), - ("boxes[boxes.findIndex(x=>x.id==edited.id)]=edited;persist();closeModal('editor');","boxes[boxes.findIndex(x=>x.id==edited.id)]=edited;persistCatalog('catalog.save');closeModal('editor');"), - ("boxes=boxes.filter(x=>x.id!=edited.id);persist();closeModal('editor');","boxes=boxes.filter(x=>x.id!=edited.id);persistCatalog('catalog.delete');closeModal('editor');") - ] - for a,b in replacements: - if a not in legacy: raise SystemExit('legacy CRUD marker missing: '+a[:80]) - legacy=legacy.replace(a,b,1) - write('public/legacy/bootstrap.js',legacy) - - # Performance loader + release identifiers. - perf=read('public/core/performance.js') - perf=perf.replace("const VERSION='17.7.0';\n const RELEASE='20260908-v17-7-0-architecture-foundation';","const VERSION='17.7.1';\n const RELEASE='20260909-v17-7-1-data-layer-adoption';",1) - for a,b in [ - ("window.CateriumDataV1770||document.getElementById('cateriumDataV1770Script')","window.CateriumDataV1771||document.getElementById('cateriumDataV1771Script')"), - ("script.id='cateriumDataV1770Script'","script.id='cateriumDataV1771Script'"), - ("core/data-layer-v1770.js?v=${RELEASE}","core/data-layer-v1771.js?v=${RELEASE}"), - ("Не загрузился data-layer-v1770.js","Не загрузился data-layer-v1771.js") - ]: - if a not in perf: raise SystemExit('performance marker missing: '+a) - perf=perf.replace(a,b,1) - write('public/core/performance.js',perf) - - # Runtime stability version. - repl('public/app-runtime.js',"const VERSION = '17.7.0';\n const RELEASE = 'v17.7.0 Architecture Foundation';","const VERSION = '17.7.1';\n const RELEASE = 'v17.7.1 Data Layer Adoption';",1) - - # Browser cache identifiers. - sw=read('public/service-worker.js') - for a,b in [(OLD_CACHE,NEW_CACHE),(OLD_RELEASE,NEW_RELEASE),('data-layer-v1770.js','data-layer-v1771.js')]: - if a not in sw: raise SystemExit('service worker marker missing: '+a) - sw=sw.replace(a,b) - write('public/service-worker.js',sw) - repl('public/index.html',OLD_RELEASE,NEW_RELEASE) - - # Package metadata. - pkg=json.loads(read('package.json'));pkg['version']='17.7.1';pkg['scripts']['check:syntax']=pkg['scripts']['check:syntax'].replace('core/data-layer-v1770.js','core/data-layer-v1771.js');write('package.json',json.dumps(pkg,ensure_ascii=False,indent=2)+'\n') - lock=json.loads(read('package-lock.json'));lock['version']='17.7.1';lock['packages']['']['version']='17.7.1';write('package-lock.json',json.dumps(lock,ensure_ascii=False,indent=2)+'\n') - - # Release manifest + notes. - manifest=json.loads(read('docs/release-manifest.json')) - manifest['version']='v17.7.1';manifest['pwaCache']=NEW_CACHE;manifest['notes']='Data layer adoption: base order save/status/delete and catalog save/delete paths now write through Caterium Data Layer with legacy local persistence retained as a fallback.';manifest['release']=NEW_RELEASE;manifest['stabilityLoggerVersion']='17.7.1';manifest['dataLayer']='core/data-layer-v1771.js';manifest['dataLayerPhase']=2;manifest['dataLayerLegacyOrderWrites']=True;manifest['dataLayerLegacyCatalogWrites']=True;manifest['legacyStateKept']=True - write('docs/release-manifest.json',json.dumps(manifest,ensure_ascii=False,indent=2)+'\n') - write('docs/releases/V17.7.1-CHANGES.txt','''Caterium v17.7.1 — Data Layer Adoption\nDate: 2026-09-09\n\n1. Moves the base order create/update, status and delete write paths through Caterium Data Layer.\n2. Moves base catalog item save/delete write paths through the same data layer.\n3. Adds a catalog repository next to the orders repository with list/get/replace/upsert/remove operations.\n4. Keeps the legacy persist() path as a compatibility fallback so existing cloud/local clients are not cut over abruptly.\n5. Keeps CateriumDataV1770 as a compatibility alias while exposing CateriumDataV1771 as the current API.\n6. Server order automation remains compatible and continues applying normalized server changes through CateriumData.\n7. PWA cache/versioning and stability telemetry are advanced to v17.7.1.\n8. Adds regression checks for order/catalog repositories and legacy CRUD routing.\n''') - - # Static checks. - static=read('tests/static-security.mjs') - static=static.replace("dataLayer=readPub('core/data-layer-v1770.js')","dataLayer=readPub('core/data-layer-v1771.js')",1) - static=static.replace("v17-7-0-architecture-foundation')||!sw.includes('data-layer-v1770.js')","v17-7-1-data-layer-adoption')||!sw.includes('data-layer-v1771.js')",1) - static=static.replace("20260908-v17-7-0-architecture-foundation')","20260909-v17-7-1-data-layer-adoption')",1) - static=static.replace("if(!performance.includes('loadDataLayer')||!performance.includes('loadServerAutomation'))fail('v17.7.0 foundation loaders missing');else ok('v17.7.0 foundation loaders present');","if(!performance.includes('loadDataLayer')||!performance.includes('data-layer-v1771.js')||!performance.includes('loadServerAutomation'))fail('v17.7.1 data layer loaders missing');else ok('v17.7.1 data layer loaders present');",1) - static=static.replace("if(!dataLayer.includes(\"const VERSION='17.7.0'\")||!dataLayer.includes('ordersRepo')||!dataLayer.includes('applyServerOrders'))fail('v17.7.0 data layer missing');else ok('v17.7.0 data layer present');","if(!dataLayer.includes(\"const VERSION='17.7.1'\")||!dataLayer.includes('ordersRepo')||!dataLayer.includes('catalogRepo')||!dataLayer.includes('applyServerOrders')||!dataLayer.includes('CateriumDataV1770=api'))fail('v17.7.1 data layer missing');else ok('v17.7.1 data layer present');",1) - static=static.replace("\"const VERSION = '17.7.0'\"","\"const VERSION = '17.7.1'\"",1) - insert="\nif(!legacy.includes('persistOrders(\'order.save\')')||!legacy.includes('persistOrders(\'order.status\')')||!legacy.includes('persistOrders(\'order.delete\')')||!legacy.includes('persistCatalog(\'catalog.save\')')||!legacy.includes('persistCatalog(\'catalog.delete\')'))fail('legacy CRUD is not routed through data layer');else ok('legacy CRUD routes through data layer');\n" - static=static.replace("if(!legacy.includes('sunEsc(')||!legacy.includes('sunAttr('))fail('legacy bootstrap is not using shared escaping');else ok('legacy bootstrap escapes text and attributes');", "if(!legacy.includes('sunEsc(')||!legacy.includes('sunAttr('))fail('legacy bootstrap is not using shared escaping');else ok('legacy bootstrap escapes text and attributes');"+insert,1) - write('tests/static-security.mjs',static) - - # Release checks: advance current-version assertions but keep the v17.7.0 server migration/module checks intact. - release=read('tests/release-check.mjs') - release=release.replace("const index=read('index.html'),runtime=read('app-runtime.js'),sw=read('service-worker.js'),css=read('core/stability-v1760.css'),performance=read('core/performance.js'),ops=read('core/ops-ux-v1762.js'),hotfix=read('core/hotfix-v1763.js'),ux=read('core/ux-fixes-v1764.js'),classic=read('core/classic-offer-pdf-v1767.js'),developerUX=read('core/developer-console-v1768.js'),offerWorkspace=read('core/offer-workspace-v1769.js');","const index=read('index.html'),runtime=read('app-runtime.js'),sw=read('service-worker.js'),css=read('core/stability-v1760.css'),performance=read('core/performance.js'),dataLayer=read('core/data-layer-v1771.js'),legacy=read('legacy/bootstrap.js'),ops=read('core/ops-ux-v1762.js'),hotfix=read('core/hotfix-v1763.js'),ux=read('core/ux-fixes-v1764.js'),classic=read('core/classic-offer-pdf-v1767.js'),developerUX=read('core/developer-console-v1768.js'),offerWorkspace=read('core/offer-workspace-v1769.js');",1) - release=release.replace("check(sw.includes('v75-20260908-v17-7-0-architecture-foundation')&&sw.includes('data-layer-v1770.js')","check(sw.includes('v76-20260909-v17-7-1-data-layer-adoption')&&sw.includes('data-layer-v1771.js')",1) - release=release.replace("check(index.includes('20260908-v17-7-0-architecture-foundation')","check(index.includes('20260909-v17-7-1-data-layer-adoption')",1) - release=release.replace("check(String(releaseManifest.pwaCache||'').includes('v75-20260908-v17-7-0-architecture-foundation')","check(String(releaseManifest.pwaCache||'').includes('v76-20260909-v17-7-1-data-layer-adoption')",1) - release=release.replace("['17.6.2','17.6.3','17.6.4','17.6.5','17.6.6','17.6.7','17.6.8','17.6.9','17.7.0']","['17.6.2','17.6.3','17.6.4','17.6.5','17.6.6','17.6.7','17.6.8','17.6.9','17.7.0','17.7.1']",1) - release=release.replace("release notes exist through v17.7.0","release notes exist through v17.7.1",1) - release=release.replace("runtime.includes(\"const VERSION = '17.7.0'\")","runtime.includes(\"const VERSION = '17.7.1'\")",1) - release=release.replace("check(pkg.version==='17.7.0','package version is v17.7.0');","check(pkg.version==='17.7.1','package version is v17.7.1');") - release=release.replace("check(index.includes('20260908-v17-7-0-architecture-foundation'),'index cache bust is v17.7.0');","check(index.includes('20260909-v17-7-1-data-layer-adoption'),'index cache bust is v17.7.1');",1) - release=release.replace("check(sw.includes('v75-20260908-v17-7-0-architecture-foundation')&&sw.includes('data-layer-v1770.js')&&sw.includes('server-automation-v1770.js'),'PWA caches architecture foundation modules');","check(sw.includes('v76-20260909-v17-7-1-data-layer-adoption')&&sw.includes('data-layer-v1771.js')&&sw.includes('server-automation-v1770.js'),'PWA caches current data layer and server automation modules');",1) - release=release.replace("check(fs.existsSync(path.join(root,'public/core/data-layer-v1770.js'))&&fs.existsSync(path.join(root,'public/core/server-automation-v1770.js')),'data layer and server automation modules exist');","check(fs.existsSync(path.join(root,'public/core/data-layer-v1771.js'))&&fs.existsSync(path.join(root,'public/core/server-automation-v1770.js')),'data layer and server automation modules exist');",1) - release=release.replace("check(runtime.includes(\"const VERSION = '17.7.0'\")&&runtime.includes(\"v17.7.0 Architecture Foundation\"),'stability logger reports v17.7.0');","check(runtime.includes(\"const VERSION = '17.7.1'\")&&runtime.includes(\"v17.7.1 Data Layer Adoption\"),'stability logger reports v17.7.1');",1) - extra="\ncheck(dataLayer.includes(\"const VERSION='17.7.1'\")&&dataLayer.includes('catalogRepo')&&dataLayer.includes('CateriumDataV1770=api'),'v17.7.1 data layer exposes order/catalog repositories with compatibility alias');\ncheck(legacy.includes(\"persistOrders('order.save')\")&&legacy.includes(\"persistOrders('order.status')\")&&legacy.includes(\"persistOrders('order.delete')\")&&legacy.includes(\"persistCatalog('catalog.save')\")&&legacy.includes(\"persistCatalog('catalog.delete')\"),'base legacy CRUD routes through data layer');\ncheck(releaseManifest.dataLayerPhase===2&&releaseManifest.dataLayerLegacyOrderWrites===true&&releaseManifest.dataLayerLegacyCatalogWrites===true,'release manifest records data layer phase 2');\n" - release=release.replace("if(bad)process.exit(1);",extra+"if(bad)process.exit(1);",1) - write('tests/release-check.mjs',release) - - # E2E version expectations + focused repository smoke test. - app=read('tests/app.spec.mjs').replace("'17.7.0'","'17.7.1'").replace('const VERSION = \'17.7.0\'','const VERSION = \'17.7.1\'') - smoke=r''' - -test('v17.7.1 data layer serves orders and catalog with v17.7.0 compatibility alias', async ({ page }) => { - await page.goto('/index.html',{waitUntil:'domcontentloaded'}); - await page.waitForFunction(()=>Boolean(window.CateriumDataV1771),null,{timeout:5000}); - const result=await page.evaluate(()=>{ - const d=window.CateriumDataV1771; - const beforeOrders=d.orders.list(),beforeCatalog=d.catalog.list(); - let orderEvent='',catalogEvent=''; - const offOrder=d.subscribe('orders',e=>{orderEvent=e.reason}); - const offCatalog=d.subscribe('catalog',e=>{catalogEvent=e.reason}); - d.orders.replace([...beforeOrders,{id:'qa-v1771',event:'QA',lines:[]}],{persistLocal:false,reason:'qa-order'}); - d.catalog.replace([...beforeCatalog,{id:'qa-v1771',name:'QA item',price:0,ingredients:[]}],{persistLocal:false,reason:'qa-catalog'}); - const hasOrder=Boolean(d.orders.get('qa-v1771')),hasCatalog=Boolean(d.catalog.get('qa-v1771')); - d.orders.replace(beforeOrders,{persistLocal:false,reason:'qa-restore'}); - d.catalog.replace(beforeCatalog,{persistLocal:false,reason:'qa-restore'}); - offOrder();offCatalog(); - return {version:d.VERSION,alias:window.CateriumDataV1770===d,hasOrder,hasCatalog,orderEvent,catalogEvent}; - }); - expect(result.version).toBe('17.7.1');expect(result.alias).toBe(true);expect(result.hasOrder).toBe(true);expect(result.hasCatalog).toBe(true);expect(result.orderEvent).toBe('qa-restore');expect(result.catalogEvent).toBe('qa-restore'); -}); -''' - if "v17.7.1 data layer serves orders and catalog" not in app: app+=smoke - write('tests/app.spec.mjs',app) - PY - - run: npm install - - run: npm run check:deploy - - name: Remove one-time workflow - run: rm .github/workflows/release-v17-7-1.yml - - name: Commit v17.7.1 - run: | - git config user.name github-actions[bot] - git config user.email 41898282+github-actions[bot]@users.noreply.github.com + rm -f .github/workflows/release-v17-7-1.yml ops/release_v1771.py + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git add -A - git commit -m "Caterium v17.7.1 — data layer adoption" + git commit -m "Caterium v17.7.1 - data layer adoption" git push