fix: register all cron jobs in twenty-app-dev image (#20167)

## Summary

The `twenty-app-dev` Docker image previously passed `--dev-mode` to
`cron:register:all`, which skipped all calendar, messaging, and workflow
sync cron jobs (only 4 generic crons were registered). This caused
periodic sync to silently stop after the initial import for community
members using the dev image as their actual instance.

## What changed

- Removed `--dev-mode` flag from
`packages/twenty-docker/twenty-app-dev/rootfs/etc/s6-overlay/scripts/register-crons.sh`
so the dev image registers all cron jobs (matching production behavior)
- Removed the now-unused `--dev-mode` option, `DEV_MODE_COMMANDS` set,
and conditional filtering logic from `cron-register-all.command.ts`

## Why this is safe

- **No log noise**: cron jobs gracefully no-op when no connected
accounts exist — they query for pending channels, find zero, and exit
early
- **No false banner**: the "reconnect account" banner only shows when a
user explicitly connected an account whose OAuth later fails, which is
correct behavior. No seed/demo data creates connected accounts, so a
fresh dev instance won't see any banner
- **Hiding crons just hid the symptom**: silently breaking sync with no
user feedback is worse than showing the banner if OAuth is misconfigured

## Context

Surfaced by a community member who reported that calendar sync cron jobs
never appeared in the queue after restarting the dev image, and only the
initial import worked. `--dev-mode` was added in #19138 as an
optimization for development but it doesn't match how the dev image is
actually used by community members deploying Twenty.

## Test plan

- [ ] Build/run the `twenty-app-dev` image
- [ ] Confirm worker logs show all cron jobs registering (calendar,
messaging, workflow, etc.)
- [ ] With no connected accounts: confirm no errors or log noise
- [ ] With a connected Google calendar: confirm periodic sync triggers
after ~5 minutes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Félix Malfait
2026-05-01 07:51:21 +02:00
committed by GitHub
parent 85752f8a61
commit c3a320c27b
2 changed files with 4 additions and 35 deletions
@@ -4,6 +4,6 @@ set -e
echo "==> START Registering cron jobs"
cd /app/packages/twenty-server
yarn command:prod cron:register:all --dev-mode
yarn command:prod cron:register:all
echo "==> DONE"
@@ -1,6 +1,6 @@
import { Logger } from '@nestjs/common';
import { Command, CommandRunner, Option } from 'nest-commander';
import { Command, CommandRunner } from 'nest-commander';
import { MarketplaceCatalogSyncCronCommand } from 'src/engine/core-modules/application/application-marketplace/crons/commands/marketplace-catalog-sync.cron.command';
import { StaleRegistrationCleanupCronCommand } from 'src/engine/core-modules/application/application-oauth/stale-registration-cleanup/commands/stale-registration-cleanup.cron.command';
@@ -68,33 +68,8 @@ export class CronRegisterAllCommand extends CommandRunner {
super();
}
private devMode = false;
@Option({
flags: '--dev-mode',
description:
'Only register cron jobs relevant to app development (cron triggers, marketplace sync, version check, stale cleanup)',
required: false,
})
parseDevMode(): boolean {
this.devMode = true;
return true;
}
private static readonly DEV_MODE_COMMANDS = new Set([
'CronTrigger',
'MarketplaceCatalogSync',
'ApplicationVersionCheck',
'StaleRegistrationCleanup',
]);
async run(): Promise<void> {
this.logger.log(
this.devMode
? 'Registering app-dev cron jobs...'
: 'Registering all background sync cron jobs...',
);
this.logger.log('Registering all background sync cron jobs...');
const allCommands = [
{
@@ -195,18 +170,12 @@ export class CronRegisterAllCommand extends CommandRunner {
},
];
const commands = this.devMode
? allCommands.filter(({ name }) =>
CronRegisterAllCommand.DEV_MODE_COMMANDS.has(name),
)
: allCommands;
let successCount = 0;
let failureCount = 0;
const failures: string[] = [];
const successes: string[] = [];
for (const { name, command } of commands) {
for (const { name, command } of allCommands) {
try {
this.logger.log(`Registering ${name} cron job...`);
await command.run();