mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-16 21:53:07 +00:00
Improve pull request flow, add branch selection for worktree creation, fix auto-mode concurrency count (#787)
* Changes from fix/fetch-before-pull-fetch * feat: Improve pull request flow, add branch selection for worktree creation, fix for automode concurrency count * feat: Add validation for remote names and improve error handling * Address PR comments and mobile layout fixes * ``` refactor: Extract PR target resolution logic into dedicated service ``` * feat: Add app shell UI and improve service imports. Address PR comments * fix: Improve security validation and cache handling in git operations * feat: Add GET /list endpoint and improve parameter handling * chore: Improve validation, accessibility, and error handling across apps * chore: Format vite server port configuration * fix: Add error handling for gh pr list command and improve offline fallbacks * fix: Preserve existing PR creation time and improve remote handling
This commit is contained in:
@@ -36,7 +36,7 @@ const buildHash = getBuildHash();
|
||||
/**
|
||||
* Vite plugin to inject the build hash into sw.js for cache busting.
|
||||
*
|
||||
* Problem: CACHE_NAME = 'automaker-v3' is hardcoded in the service worker.
|
||||
* Problem: CACHE_NAME is hardcoded in the service worker.
|
||||
* After a deployment, users may continue getting stale HTML from the SW cache
|
||||
* if someone forgets to manually bump the version.
|
||||
*
|
||||
@@ -44,7 +44,10 @@ const buildHash = getBuildHash();
|
||||
* SW cache is automatically invalidated on each deployment.
|
||||
*/
|
||||
function swCacheBuster(): Plugin {
|
||||
const CACHE_NAME_PATTERN = /const CACHE_NAME = 'automaker-v3';/;
|
||||
// Single constant for the cache name prefix — bump this when changing the SW cache version.
|
||||
const CACHE_NAME_BASE = 'automaker-v5';
|
||||
const CACHE_NAME_PATTERN = new RegExp(`const CACHE_NAME = '${CACHE_NAME_BASE}';`);
|
||||
const CRITICAL_ASSETS_PATTERN = /const CRITICAL_ASSETS = \[\];/;
|
||||
return {
|
||||
name: 'sw-cache-buster',
|
||||
// In build mode: copy sw.js to output with hash injected
|
||||
@@ -56,21 +59,65 @@ function swCacheBuster(): Plugin {
|
||||
console.warn('[sw-cache-buster] sw.js not found in dist/ — skipping cache bust');
|
||||
return;
|
||||
}
|
||||
const swContent = fs.readFileSync(swPath, 'utf-8');
|
||||
let swContent = fs.readFileSync(swPath, 'utf-8');
|
||||
if (!CACHE_NAME_PATTERN.test(swContent)) {
|
||||
console.error(
|
||||
'[sw-cache-buster] Could not find CACHE_NAME declaration in sw.js. ' +
|
||||
'The service worker cache will NOT be busted on this deploy! ' +
|
||||
"Check that public/sw.js still contains: const CACHE_NAME = 'automaker-v3';"
|
||||
`Check that public/sw.js still contains: const CACHE_NAME = '${CACHE_NAME_BASE}';`
|
||||
);
|
||||
return;
|
||||
}
|
||||
const updated = swContent.replace(
|
||||
swContent = swContent.replace(
|
||||
CACHE_NAME_PATTERN,
|
||||
`const CACHE_NAME = 'automaker-v3-${buildHash}';`
|
||||
`const CACHE_NAME = '${CACHE_NAME_BASE}-${buildHash}';`
|
||||
);
|
||||
fs.writeFileSync(swPath, updated, 'utf-8');
|
||||
console.log(`[sw-cache-buster] Injected build hash: automaker-v3-${buildHash}`);
|
||||
console.log(`[sw-cache-buster] Injected build hash: ${CACHE_NAME_BASE}-${buildHash}`);
|
||||
|
||||
// Extract critical asset URLs from the built index.html and inject them
|
||||
// into the SW so it can precache them on install (not just after the main
|
||||
// thread sends PRECACHE_ASSETS). This ensures the very first visit populates
|
||||
// the immutable cache, so PWA cold starts after memory eviction serve from cache.
|
||||
const indexHtmlPath = path.resolve(__dirname, 'dist', 'index.html');
|
||||
if (fs.existsSync(indexHtmlPath)) {
|
||||
if (!CRITICAL_ASSETS_PATTERN.test(swContent)) {
|
||||
console.warn(
|
||||
'[sw-cache-buster] CRITICAL_ASSETS placeholder not found in sw.js — ' +
|
||||
'precaching of critical assets was not injected. ' +
|
||||
'Check that public/sw.js still contains: const CRITICAL_ASSETS = [];'
|
||||
);
|
||||
} else {
|
||||
const indexHtml = fs.readFileSync(indexHtmlPath, 'utf-8');
|
||||
// Use a Set to deduplicate — assetRegex may match the same path in both href and src.
|
||||
const criticalAssetsSet = new Set<string>();
|
||||
|
||||
// Extract hashed asset URLs from all link and script tags.
|
||||
// These are the JS/CSS bundles Vite produces with content hashes.
|
||||
// Match: href="./assets/..." or src="./assets/..."
|
||||
const assetRegex = /(?:href|src)="(\.\/(assets\/[^"]+))"/g;
|
||||
let match;
|
||||
while ((match = assetRegex.exec(indexHtml)) !== null) {
|
||||
const assetPath = '/' + match[2]; // Convert ./assets/... to /assets/...
|
||||
// Only include JS and CSS — skip images, fonts, etc. to keep cache small
|
||||
if (assetPath.endsWith('.js') || assetPath.endsWith('.css')) {
|
||||
criticalAssetsSet.add(assetPath);
|
||||
}
|
||||
}
|
||||
|
||||
const criticalAssets = Array.from(criticalAssetsSet);
|
||||
if (criticalAssets.length > 0) {
|
||||
swContent = swContent.replace(
|
||||
CRITICAL_ASSETS_PATTERN,
|
||||
`const CRITICAL_ASSETS = ${JSON.stringify(criticalAssets)};`
|
||||
);
|
||||
console.log(
|
||||
`[sw-cache-buster] Injected ${criticalAssets.length} critical assets for install-time precaching`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeFileSync(swPath, swContent, 'utf-8');
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -97,11 +144,16 @@ function mobilePreloadOptimizer(): Plugin {
|
||||
// - vendor-xterm: /terminal route only
|
||||
// - vendor-codemirror: spec/XML editor routes only
|
||||
// - vendor-markdown: agent view, wiki, and other markdown-rendering routes
|
||||
// - vendor-icons: lucide-react icons (587 KB) — not needed before React mounts.
|
||||
// The !authChecked loading state uses a pure CSS spinner instead of a Lucide icon,
|
||||
// so icons are not required until the authenticated UI renders (by which time this
|
||||
// prefetch has usually completed on typical connections).
|
||||
const deferredChunks = [
|
||||
'vendor-reactflow',
|
||||
'vendor-xterm',
|
||||
'vendor-codemirror',
|
||||
'vendor-markdown',
|
||||
'vendor-icons',
|
||||
];
|
||||
|
||||
return {
|
||||
@@ -193,11 +245,11 @@ export default defineConfig(({ command }) => {
|
||||
},
|
||||
server: {
|
||||
host: process.env.HOST || '0.0.0.0',
|
||||
port: parseInt(process.env.TEST_PORT || '3007', 10),
|
||||
port: parseInt(process.env.TEST_PORT || process.env.AUTOMAKER_WEB_PORT || '3007', 10),
|
||||
allowedHosts: true,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: 'http://localhost:3008',
|
||||
target: 'http://localhost:' + (process.env.AUTOMAKER_SERVER_PORT ?? '5008'),
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user