## Summary Follow-up to the Cloudflare/OpenNext migration (#20741). Now that the legacy `twenty-website` package was already removed in #20270, the `-new` suffix on the marketing site package is no longer meaningful. ## What changes - **Directory rename**: `git mv packages/twenty-website-new packages/twenty-website` (1213 files moved, no content change) - **Package + nx config**: `package.json` and `project.json` name fields updated, `sourceRoot` repointed - **Source refs**: `load-local-articles.ts` and `load-local-release-notes.ts` had a hardcoded `'twenty-website-new'` segment in their monorepo-root fallback path; `app/[locale]/releases/page.tsx` had display strings showing where to add content - **External refs**: root `package.json` workspaces, root `CLAUDE.md` / `README.md`, `twenty-sdk` + `create-twenty-app` READMEs, `.vscode/twenty.code-workspace`, `.cursor/rules/changelog-process.mdc`, Crowdin config + the three `website-i18n-*` CI workflows + `ci-website.yaml` - **Docker cleanup**: `packages/twenty-docker/twenty-website-new/Dockerfile` deleted; the two Makefile targets (`prod-website-new-build` / `prod-website-new-run`) that referenced it removed — EKS deploy was retired in the Cloudflare migration - **`yarn.lock`** regenerated against the new workspace path ## What's deliberately not in this PR The dev hostname `website-new.twenty-main.com` in `wrangler.jsonc` stays for now. Migrating it to `website.twenty-main.com` needs coordinated DNS deletion (current CNAME points at the legacy Docusaurus NLB and serves 503s) and removal of the matching legacy `website` Helm chart in `twenty-infra`. Flagged as a separate cleanup. Companion infra PR: https://github.com/twentyhq/twenty-infra/pull/682 (workflow paths + Terraform ECR + docs) ## Test plan - [x] `yarn install --immutable` resolves clean against the new path - [x] `npx nx typecheck twenty-website` passes - [x] `npx nx lint twenty-website` passes - [ ] CI on this PR confirms the same on a fresh checkout - [ ] After merge: trigger `Deploy Website` workflow against `environment=dev` to confirm the renamed working-directory deploys correctly
120 lines
3.5 KiB
JavaScript
120 lines
3.5 KiB
JavaScript
#!/usr/bin/env node
|
|
import { execFile } from 'node:child_process';
|
|
import { readFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { promisify } from 'node:util';
|
|
|
|
const execFileAsync = promisify(execFile);
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const ROOT = path.resolve(__dirname, '..');
|
|
|
|
const LOTTIE_PATH = path.join(
|
|
ROOT,
|
|
'public',
|
|
'lottie',
|
|
'stepper',
|
|
'stepper.lottie',
|
|
);
|
|
const ANIMATION_ENTRY = 'animations/main.json';
|
|
const FRAME_MAP_PATH = path.join(
|
|
ROOT,
|
|
'src',
|
|
'sections',
|
|
'HomeStepper',
|
|
'components',
|
|
'Visual',
|
|
'use-dot-lottie-scroll-sync.ts',
|
|
);
|
|
|
|
const EXPECTED_CONSTANT_REGEX =
|
|
/(?:export\s+)?const\s+HOME_STEPPER_LOTTIE_EXPECTED_TOTAL_FRAMES\s*=\s*(\d+)\s*;/;
|
|
|
|
function fail(message) {
|
|
// eslint-disable-next-line no-console
|
|
console.error(`\n check-lottie-frames: ${message}\n`);
|
|
process.exitCode = 1;
|
|
}
|
|
|
|
async function readExpectedTotalFrames() {
|
|
const source = await readFile(FRAME_MAP_PATH, 'utf8');
|
|
const match = source.match(EXPECTED_CONSTANT_REGEX);
|
|
if (match === null) {
|
|
throw new Error(
|
|
`couldn't find HOME_STEPPER_LOTTIE_EXPECTED_TOTAL_FRAMES in ${path.relative(ROOT, FRAME_MAP_PATH)}. ` +
|
|
'Has the constant been renamed? Update both the TS file and the regex in this script.',
|
|
);
|
|
}
|
|
return Number.parseInt(match[1], 10);
|
|
}
|
|
|
|
async function readActualTotalFrames() {
|
|
let stdout;
|
|
try {
|
|
const result = await execFileAsync(
|
|
'unzip',
|
|
['-p', LOTTIE_PATH, ANIMATION_ENTRY],
|
|
{ maxBuffer: 32 * 1024 * 1024, encoding: 'buffer' },
|
|
);
|
|
stdout = result.stdout;
|
|
} catch (error) {
|
|
if (error?.code === 'ENOENT') {
|
|
throw new Error(
|
|
'`unzip` binary not found on PATH. Install it (Debian/Ubuntu: `apt install unzip`, macOS ships with it) — ' +
|
|
'this script needs it to read the Lottie animation JSON.',
|
|
);
|
|
}
|
|
throw new Error(
|
|
`failed to extract ${ANIMATION_ENTRY} from ${path.relative(ROOT, LOTTIE_PATH)}: ${error?.message ?? error}`,
|
|
);
|
|
}
|
|
|
|
let animation;
|
|
try {
|
|
animation = JSON.parse(stdout.toString('utf8'));
|
|
} catch (error) {
|
|
throw new Error(
|
|
`${ANIMATION_ENTRY} inside the .lottie file is not valid JSON: ${error?.message ?? error}`,
|
|
);
|
|
}
|
|
|
|
const ip = animation?.ip;
|
|
const op = animation?.op;
|
|
if (typeof ip !== 'number' || typeof op !== 'number') {
|
|
throw new Error(
|
|
`${ANIMATION_ENTRY} is missing numeric \`ip\` / \`op\` fields ` +
|
|
`(got ip=${JSON.stringify(ip)}, op=${JSON.stringify(op)}). ` +
|
|
'Has the Lottie schema changed?',
|
|
);
|
|
}
|
|
return Math.floor(op - ip);
|
|
}
|
|
|
|
async function main() {
|
|
const [expected, actual] = await Promise.all([
|
|
readExpectedTotalFrames(),
|
|
readActualTotalFrames(),
|
|
]);
|
|
|
|
if (expected !== actual) {
|
|
fail(
|
|
`Lottie totalFrames mismatch — expected ${expected} (per HOME_STEPPER_LOTTIE_EXPECTED_TOTAL_FRAMES), ` +
|
|
`got ${actual} from ${path.relative(ROOT, LOTTIE_PATH)}.\n ` +
|
|
' The home-stepper scroll → frame map is keyed to the authored timeline; ' +
|
|
'either:\n 1. revert the Lottie re-export, or\n 2. update HOME_STEPPER_LOTTIE_EXPECTED_TOTAL_FRAMES ' +
|
|
'and the STEP_*_END anchors in home-stepper-lottie-frame-map.ts together.',
|
|
);
|
|
return;
|
|
}
|
|
|
|
// eslint-disable-next-line no-console
|
|
console.log(
|
|
`check-lottie-frames: OK (stepper.lottie totalFrames = ${actual}).`,
|
|
);
|
|
}
|
|
|
|
main().catch((error) => {
|
|
fail(error?.message ?? String(error));
|
|
});
|