feat(release): prepare 1.1.0 candidate
This commit is contained in:
parent
5a34f66981
commit
5205dcdfa9
736 changed files with 115667 additions and 12203 deletions
88
scripts/deploy-site-to-nas.js
Normal file
88
scripts/deploy-site-to-nas.js
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// scripts/deploy-site-to-nas.js
|
||||
const { spawnSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const MOBILE_RELEASE_PATTERN = /(?:\.apk|\.aab|android[^/\\]*\.zip|signed[^/\\]*\.zip)$/i;
|
||||
const MOBILE_DOWNLOAD_REFERENCE = /(?:d3ro-voice[^"']*\.apk|git\.chanpaca\.net\/attachments\/(?:0b015367-dd8b-488c-8cc0-4db413b51792|d2e1b123-5678-496a-bf74-bc188938c999))/i;
|
||||
|
||||
function assertNoMobileArtifacts(root) {
|
||||
if (!fs.existsSync(root)) return;
|
||||
const pending = [root];
|
||||
while (pending.length > 0) {
|
||||
const current = pending.pop();
|
||||
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
||||
const candidate = path.join(current, entry.name);
|
||||
if (entry.isSymbolicLink()) throw new Error(`Refusing symlink in deploy tree: ${candidate}`);
|
||||
if (entry.isDirectory()) pending.push(candidate);
|
||||
if (entry.isFile() && MOBILE_RELEASE_PATTERN.test(entry.name)) {
|
||||
throw new Error(`Unsealed mobile artifact blocked from NAS deploy: ${candidate}`);
|
||||
}
|
||||
if (entry.isFile() && /\.(?:html|js|json)$/i.test(entry.name)) {
|
||||
const source = fs.readFileSync(candidate, 'utf8');
|
||||
if (MOBILE_DOWNLOAD_REFERENCE.test(source)) {
|
||||
throw new Error(`Legacy mobile download link blocked from NAS deploy: ${candidate}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function deploy() {
|
||||
assertNoMobileArtifacts(path.resolve(__dirname, '../site/dist'));
|
||||
console.log('=== 1. Building Site ===');
|
||||
const build = spawnSync('npm', ['run', 'build', '--prefix', 'site'], { stdio: 'inherit', shell: true });
|
||||
if (build.status !== 0) throw new Error('Site build failed');
|
||||
|
||||
assertNoMobileArtifacts(path.resolve(__dirname, '../site/dist'));
|
||||
|
||||
console.log('=== 2. Creating tar archive of site/dist ===');
|
||||
const tarPath = path.resolve(__dirname, '../out/site-dist.tar');
|
||||
if (!fs.existsSync(path.dirname(tarPath))) fs.mkdirSync(path.dirname(tarPath), { recursive: true });
|
||||
|
||||
// Use tar to create archive
|
||||
const tarRes = spawnSync('tar', ['-cf', tarPath, '-C', 'site/dist', '.'], { stdio: 'inherit', shell: true });
|
||||
if (tarRes.status !== 0) throw new Error('Tar creation failed');
|
||||
console.log(`Created archive: ${tarPath} (${(fs.statSync(tarPath).size / 1024 / 1024).toFixed(2)} MB)`);
|
||||
|
||||
console.log('=== 3. Uploading archive to Synology NAS via SCP ===');
|
||||
const scpRes = spawnSync('scp', [
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
tarPath,
|
||||
'yunchan@192.168.0.39:/volume1/docker/d3ro/site-dist.tar'
|
||||
], { stdio: 'inherit', shell: true });
|
||||
if (scpRes.status !== 0) throw new Error('SCP upload failed');
|
||||
|
||||
console.log('=== 4. Extracting on NAS and applying to d3ro_voice_api container ===');
|
||||
const sshCmd = `
|
||||
mkdir -p /volume1/docker/d3ro/wwwroot &&
|
||||
tar -xf /volume1/docker/d3ro/site-dist.tar -C /volume1/docker/d3ro/wwwroot &&
|
||||
docker cp /volume1/docker/d3ro/wwwroot/. d3ro_voice_api:/app/wwwroot/ &&
|
||||
docker exec d3ro_voice_api ls -la /app/wwwroot &&
|
||||
docker exec d3ro_voice_api find /app/wwwroot -type f \( -name '*.apk' -o -name '*.aab' \) -print -quit | grep -q . && exit 1 || true
|
||||
`;
|
||||
|
||||
const sshRes = spawnSync('ssh', [
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
'yunchan@192.168.0.39',
|
||||
sshCmd
|
||||
], { stdio: 'inherit', shell: true });
|
||||
if (sshRes.status !== 0) throw new Error('SSH extract failed');
|
||||
|
||||
console.log('=== 5. Updating docker-compose.yml on NAS for persistent mount ===');
|
||||
const updateComposeCmd = `
|
||||
sed -i 's|- /volume1/docker/d3ro/data:/app/data|- /volume1/docker/d3ro/data:/app/data\\n - /volume1/docker/d3ro/wwwroot:/app/wwwroot|g' /volume1/docker/d3ro/docker-compose.yml || true
|
||||
`;
|
||||
spawnSync('ssh', ['-o', 'StrictHostKeyChecking=no', 'yunchan@192.168.0.39', updateComposeCmd], { stdio: 'inherit', shell: true });
|
||||
|
||||
console.log('✓ Successfully deployed site and releases to NAS!');
|
||||
}
|
||||
|
||||
module.exports = { assertNoMobileArtifacts };
|
||||
|
||||
if (require.main === module) {
|
||||
deploy().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue