ddc71dc7f2
- Rebuilt all 9 Asian language landing pages (zh-CN, zh-TW, ja, ko, th, vi, id, ms, hi) - Switched from dark to light theme per MOBILE_FIRST_STANDARD - Added Landvex Authorization section (VW-style certification flow) - Added full copy: hero, stats, how-it-works, missions, earnings, FAQ, footer - Localized currencies and payment methods per market - Build system: template + JSON translations → static HTML - Validation script ensures no missing translations or placeholder leaks - CI/CD pipeline: GitHub Actions → S3 + CloudFront - Version management: npm version patch/minor/major BREAKING CHANGE: Old placeholder pages replaced with full content
79 lines
2.3 KiB
JavaScript
79 lines
2.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Deploy to S3 + CloudFront
|
|
* Usage: node scripts/deploy.js --env=staging|production
|
|
*/
|
|
|
|
const { execSync } = require('child_process');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const ENVIRONMENTS = {
|
|
staging: {
|
|
bucket: 'quixzoom-asia-staging',
|
|
region: 'ap-southeast-1',
|
|
distributionId: process.env.CF_DIST_STAGING,
|
|
url: 'https://staging.quixzoom.asia',
|
|
},
|
|
production: {
|
|
bucket: 'quixzoom-asia',
|
|
region: 'ap-southeast-1',
|
|
distributionId: process.env.CF_DIST_PRODUCTION,
|
|
url: 'https://quixzoom.asia',
|
|
},
|
|
};
|
|
|
|
const [, , envArg] = process.argv;
|
|
const env = envArg?.replace('--env=', '') || 'staging';
|
|
|
|
if (!ENVIRONMENTS[env]) {
|
|
console.error(`❌ Unknown environment: ${env}`);
|
|
console.error('Usage: node scripts/deploy.js --env=staging|production');
|
|
process.exit(1);
|
|
}
|
|
|
|
const config = ENVIRONMENTS[env];
|
|
const distDir = path.join(__dirname, '../dist');
|
|
const manifestPath = path.join(distDir, 'manifest.json');
|
|
|
|
if (!fs.existsSync(distDir)) {
|
|
console.error('❌ No dist/ directory. Run: npm run build');
|
|
process.exit(1);
|
|
}
|
|
|
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
|
|
console.log(`🚀 Deploying quiXzoom Asia v${manifest.version} to ${env}...`);
|
|
console.log(` Bucket: ${config.bucket}`);
|
|
console.log(` Region: ${config.region}`);
|
|
console.log(` Commit: ${manifest.gitCommit}`);
|
|
console.log('');
|
|
|
|
// Sync to S3
|
|
const syncCmd = `aws s3 sync ${distDir}/ s3://${config.bucket}/ \
|
|
--delete \
|
|
--cache-control "max-age=3600" \
|
|
--region ${config.region}`;
|
|
|
|
console.log('📤 Uploading...');
|
|
execSync(syncCmd, { stdio: 'inherit' });
|
|
|
|
// Set content types
|
|
console.log('\n📝 Setting content types...');
|
|
execSync(`aws s3 cp s3://${config.bucket}/ s3://${config.bucket}/ \
|
|
--recursive --exclude "*" --include "*.html" \
|
|
--content-type "text/html; charset=utf-8" \
|
|
--metadata-directive REPLACE --region ${config.region}`, { stdio: 'inherit' });
|
|
|
|
// Invalidate CloudFront
|
|
if (config.distributionId) {
|
|
console.log('\n🔄 Invalidating CloudFront...');
|
|
execSync(`aws cloudfront create-invalidation \
|
|
--distribution-id ${config.distributionId} \
|
|
--paths "/*" --region ${config.region}`, { stdio: 'inherit' });
|
|
}
|
|
|
|
console.log(`\n✅ Deployed to ${config.url}`);
|
|
console.log(` Version: ${manifest.version}`);
|
|
console.log(` Build: ${manifest.buildTime}`);
|