feat: Add voice and video stage functionality with multi-platform project setup.
Some checks failed
Build and Release / build-and-release (push) Has been cancelled
Some checks failed
Build and Release / build-and-release (push) Has been cancelled
This commit is contained in:
@@ -16,6 +16,7 @@ const RELEASES_DIR = '/app/releases';
|
||||
const LOADING_HTML = readFileSync(join(__dirname, 'loading.html'), 'utf-8');
|
||||
|
||||
let currentDistPath = null;
|
||||
let currentCommitHash = null;
|
||||
let building = false;
|
||||
let lastBuildStatus = { status: 'idle', timestamp: null, error: null };
|
||||
|
||||
@@ -39,8 +40,15 @@ function run(cmd, opts = {}) {
|
||||
execSync(cmd, { stdio: 'inherit', timeout: 600_000, ...opts });
|
||||
}
|
||||
|
||||
async function triggerBuild() {
|
||||
async function triggerBuild(webhookCommit) {
|
||||
if (building) return;
|
||||
|
||||
// Fast path: skip clone entirely if webhook provides the commit and it matches
|
||||
if (webhookCommit && webhookCommit === currentCommitHash) {
|
||||
log(`Commit ${webhookCommit} is already deployed, skipping build (webhook fast path).`);
|
||||
return;
|
||||
}
|
||||
|
||||
building = true;
|
||||
lastBuildStatus = { status: 'building', timestamp: Date.now(), error: null };
|
||||
|
||||
@@ -54,6 +62,17 @@ async function triggerBuild() {
|
||||
// Clone
|
||||
run(`git clone --depth 1 --branch ${GIT_BRANCH} ${GIT_REPO_URL} ${buildDir}`);
|
||||
|
||||
// Read the cloned commit hash
|
||||
const clonedHash = execSync('git rev-parse HEAD', { cwd: buildDir, encoding: 'utf-8' }).trim();
|
||||
log(`Cloned commit: ${clonedHash}`);
|
||||
|
||||
// Skip if this commit is already deployed
|
||||
if (clonedHash === currentCommitHash) {
|
||||
log(`Commit ${clonedHash} is already deployed, skipping build.`);
|
||||
lastBuildStatus = { status: 'skipped', timestamp: Date.now(), error: null };
|
||||
return;
|
||||
}
|
||||
|
||||
// Install deps (web workspaces only)
|
||||
run(
|
||||
'npm ci --workspace=apps/web --workspace=packages/shared --workspace=packages/platform-web --include-workspace-root',
|
||||
@@ -73,7 +92,8 @@ async function triggerBuild() {
|
||||
// Swap — instant, zero downtime
|
||||
const oldDist = currentDistPath;
|
||||
currentDistPath = releaseDir;
|
||||
log(`Swapped to new release: ${releaseDir}`);
|
||||
currentCommitHash = clonedHash;
|
||||
log(`Swapped to new release: ${releaseDir} (commit ${clonedHash})`);
|
||||
|
||||
// Clean up old release
|
||||
if (oldDist && existsSync(oldDist) && oldDist !== releaseDir) {
|
||||
@@ -105,13 +125,16 @@ app.use(compression());
|
||||
app.post('/api/webhook', express.json(), (req, res) => {
|
||||
if (building) return res.status(409).json({ error: 'Build already in progress' });
|
||||
|
||||
triggerBuild();
|
||||
// Extract commit SHA from Gitea/GitHub push webhook payload
|
||||
const webhookCommit = req.body?.after || null;
|
||||
|
||||
triggerBuild(webhookCommit);
|
||||
res.json({ message: 'Build triggered' });
|
||||
});
|
||||
|
||||
// Status endpoint
|
||||
app.get('/api/status', (_req, res) => {
|
||||
res.json({ building, ...lastBuildStatus });
|
||||
res.json({ building, commitHash: currentCommitHash, ...lastBuildStatus });
|
||||
});
|
||||
|
||||
// Static file serving + SPA fallback
|
||||
|
||||
Reference in New Issue
Block a user