@eldrforge/kodrdriv 1.2.25 → 1.2.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -362,9 +362,11 @@ const isReleaseNecessaryComparedToTarget = async (targetBranch, isDryRun)=>{
362
362
  const headSorted = sortObjectKeys(headWithoutVersion);
363
363
  const equalExceptVersion = JSON.stringify(baseSorted) === JSON.stringify(headSorted);
364
364
  if (equalExceptVersion) {
365
+ const currentVersion = headPkg.version;
366
+ const targetVersion = basePkg.version;
365
367
  return {
366
368
  necessary: false,
367
- reason: 'Only version changed in package.json (plus lockfile)'
369
+ reason: `No meaningful changes detected:\n • Current version: ${currentVersion}\n • Target branch version: ${targetVersion}\n • Only package.json version field differs\n\n To force republish: Add meaningful code changes or use --force (not yet implemented)`
368
370
  };
369
371
  }
370
372
  // Other fields changed inside package.json
@@ -434,10 +436,11 @@ const execute = async (runConfig)=>{
434
436
  try {
435
437
  const remoteExists = await run(`git ls-remote --exit-code --heads origin ${currentBranch}`).then(()=>true).catch(()=>false);
436
438
  if (remoteExists) {
437
- // Wrap git pull with lock to prevent concurrent pulls in same repo
439
+ // Use explicit fetch+merge instead of pull to avoid git config conflicts
438
440
  await runGitWithLock(process.cwd(), async ()=>{
439
- await run(`git pull origin ${currentBranch} --no-edit`);
440
- }, `pull ${currentBranch}`);
441
+ await run(`git fetch origin ${currentBranch}`);
442
+ await run(`git merge origin/${currentBranch} --no-ff --no-edit`);
443
+ }, `sync ${currentBranch}`);
441
444
  logger.info(`✅ Synced ${currentBranch} with remote`);
442
445
  } else {
443
446
  logger.info(`ℹ️ No remote ${currentBranch} branch found, will be created on first push`);
@@ -525,7 +528,7 @@ const execute = async (runConfig)=>{
525
528
  try {
526
529
  const necessity = await isReleaseNecessaryComparedToTarget(targetBranch, isDryRun);
527
530
  if (!necessity.necessary) {
528
- logger.info(`Skipping publish: ${necessity.reason}.`);
531
+ logger.info(`\n⏭️ Skipping publish: ${necessity.reason}`);
529
532
  // Emit a machine-readable marker so tree mode can detect skip and avoid propagating versions
530
533
  logger.info('KODRDRIV_PUBLISH_SKIPPED');
531
534
  return;
@@ -924,8 +927,9 @@ const execute = async (runConfig)=>{
924
927
  const remoteExists = await run(`git ls-remote --exit-code --heads origin ${targetBranch}`).then(()=>true).catch(()=>false);
925
928
  if (remoteExists) {
926
929
  await runGitWithLock(process.cwd(), async ()=>{
927
- await run(`git pull origin ${targetBranch} --no-edit`);
928
- }, `pull ${targetBranch}`);
930
+ await run(`git fetch origin ${targetBranch}`);
931
+ await run(`git merge origin/${targetBranch} --no-ff --no-edit`);
932
+ }, `sync ${targetBranch}`);
929
933
  logger.info(`✅ Synced ${targetBranch} with remote`);
930
934
  } else {
931
935
  logger.info(`ℹ️ No remote ${targetBranch} branch found, will be created on first push`);
@@ -1170,6 +1174,28 @@ const execute = async (runConfig)=>{
1170
1174
  logger.info(`Resetting ${currentBranch} to ${targetBranch} (squash merge)...`);
1171
1175
  await run(`git reset --hard ${targetBranch}`);
1172
1176
  logger.info(`✅ Reset ${currentBranch} to ${targetBranch}`);
1177
+ // After squash merge and reset, we need to force push
1178
+ // This is safe because we just merged to main and are syncing working branch
1179
+ logger.info(`🔄 Force pushing ${currentBranch} to remote (post-squash sync)...`);
1180
+ try {
1181
+ // Verify that remote working branch is ancestor of main (safety check)
1182
+ try {
1183
+ await run(`git fetch origin ${currentBranch}`);
1184
+ await run(`git merge-base --is-ancestor origin/${currentBranch} ${targetBranch}`);
1185
+ logger.verbose(`✓ Safety check passed: origin/${currentBranch} is ancestor of ${targetBranch}`);
1186
+ } catch {
1187
+ // Remote branch might not exist yet, or already in sync - both OK
1188
+ logger.verbose(`Remote ${currentBranch} does not exist or is already synced`);
1189
+ }
1190
+ // Use --force-with-lease for safer force push
1191
+ await run(`git push --force-with-lease origin ${currentBranch}`);
1192
+ logger.info(`✅ Force pushed ${currentBranch} to remote`);
1193
+ } catch (pushError) {
1194
+ // If force push fails, provide helpful message
1195
+ logger.warn(`⚠️ Could not force push ${currentBranch}: ${pushError.message}`);
1196
+ logger.warn(` You may need to manually force push:`);
1197
+ logger.warn(` git push --force-with-lease origin ${currentBranch}`);
1198
+ }
1173
1199
  } else {
1174
1200
  // For merge/rebase methods, try to merge target back into source
1175
1201
  logger.info(`Merging ${targetBranch} into ${currentBranch}...`);
@@ -1228,11 +1254,7 @@ const execute = async (runConfig)=>{
1228
1254
  logger.warn(` Please push manually: git push origin ${currentBranch}`);
1229
1255
  }
1230
1256
  } else {
1231
- if (mergeMethod === 'squash') {
1232
- logger.info(`Would reset ${currentBranch} to ${targetBranch} (squash merge)`);
1233
- } else {
1234
- logger.info(`Would merge ${targetBranch} into ${currentBranch} with --ff-only`);
1235
- }
1257
+ logger.info(`Would merge ${targetBranch} into ${currentBranch} with --ff-only`);
1236
1258
  logger.info(`Would bump version to next development version`);
1237
1259
  logger.info(`Would push ${currentBranch} to origin`);
1238
1260
  }