contribute-now 0.6.0 → 0.6.1-dev.4075d32
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.
- package/dist/index.js +145 -89
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -293,6 +293,12 @@ async function getCommitHash(ref) {
|
|
|
293
293
|
return null;
|
|
294
294
|
return stdout.trim() || null;
|
|
295
295
|
}
|
|
296
|
+
async function getCommitSubject(ref) {
|
|
297
|
+
const { exitCode, stdout } = await run(["log", "-1", "--format=%s", ref]);
|
|
298
|
+
if (exitCode !== 0)
|
|
299
|
+
return null;
|
|
300
|
+
return stdout.trim() || null;
|
|
301
|
+
}
|
|
296
302
|
async function determineRebaseStrategy(currentBranch, syncRef) {
|
|
297
303
|
const upstreamRef = await getUpstreamRef();
|
|
298
304
|
if (!upstreamRef) {
|
|
@@ -664,21 +670,21 @@ LogEngine.configure({
|
|
|
664
670
|
mode: LogMode.INFO,
|
|
665
671
|
format: {
|
|
666
672
|
includeIsoTimestamp: false,
|
|
667
|
-
includeLocalTime:
|
|
673
|
+
includeLocalTime: false,
|
|
668
674
|
includeEmoji: true
|
|
669
675
|
}
|
|
670
676
|
});
|
|
671
|
-
function success(msg) {
|
|
672
|
-
LogEngine.log(msg);
|
|
677
|
+
function success(msg, emoji = "✅") {
|
|
678
|
+
LogEngine.log(msg, undefined, { emoji });
|
|
673
679
|
}
|
|
674
|
-
function error(msg) {
|
|
675
|
-
LogEngine.error(msg);
|
|
680
|
+
function error(msg, emoji = "\uD83D\uDEA8") {
|
|
681
|
+
LogEngine.error(msg, undefined, { emoji });
|
|
676
682
|
}
|
|
677
|
-
function warn(msg) {
|
|
678
|
-
LogEngine.warn(msg);
|
|
683
|
+
function warn(msg, emoji = "⚠️") {
|
|
684
|
+
LogEngine.warn(msg, undefined, { emoji });
|
|
679
685
|
}
|
|
680
|
-
function info(msg) {
|
|
681
|
-
LogEngine.info(msg);
|
|
686
|
+
function info(msg, emoji = "ℹ️") {
|
|
687
|
+
LogEngine.info(msg, undefined, { emoji });
|
|
682
688
|
}
|
|
683
689
|
function heading(msg) {
|
|
684
690
|
console.log(`
|
|
@@ -1677,8 +1683,8 @@ async function handleCurrentBranchDeletion(currentBranch, baseBranch, config) {
|
|
|
1677
1683
|
if (rebaseResult.exitCode !== 0) {
|
|
1678
1684
|
await rebaseAbort();
|
|
1679
1685
|
warn("Rebase had conflicts — aborted to keep the repo in a clean state.");
|
|
1680
|
-
info(`Your work is saved on ${pc5.bold(newBranchName)}. After cleanup, rebase manually
|
|
1681
|
-
info(` ${pc5.bold(`git checkout ${newBranchName} && git rebase ${syncSource2.ref}`)}
|
|
1686
|
+
info(`Your work is saved on ${pc5.bold(newBranchName)}. After cleanup, rebase manually:`, "");
|
|
1687
|
+
info(` ${pc5.bold(`git checkout ${newBranchName} && git rebase ${syncSource2.ref}`)}`, "");
|
|
1682
1688
|
} else {
|
|
1683
1689
|
success(`Rebased ${pc5.bold(newBranchName)} onto ${pc5.bold(syncSource2.ref)}.`);
|
|
1684
1690
|
}
|
|
@@ -1753,7 +1759,7 @@ var clean_default = defineCommand2({
|
|
|
1753
1759
|
const mergedPR = await getMergedPRForBranch(currentBranch);
|
|
1754
1760
|
if (mergedPR) {
|
|
1755
1761
|
warn(`PR #${mergedPR.number} (${pc5.bold(mergedPR.title)}) has already been merged.`);
|
|
1756
|
-
info(`Link: ${pc5.underline(mergedPR.url)}
|
|
1762
|
+
info(`Link: ${pc5.underline(mergedPR.url)}`, "");
|
|
1757
1763
|
goneCandidates.push(currentBranch);
|
|
1758
1764
|
}
|
|
1759
1765
|
}
|
|
@@ -1827,7 +1833,7 @@ ${pc5.bold("Stale branches (remote deleted, likely squash-merged):")}`);
|
|
|
1827
1833
|
}
|
|
1828
1834
|
}
|
|
1829
1835
|
if (mergedCandidates.length === 0 && goneCandidates.length === 0) {
|
|
1830
|
-
info("No branches to clean up. Everything is tidy! \uD83E\uDDF9");
|
|
1836
|
+
info("No branches to clean up. Everything is tidy!", "\uD83E\uDDF9");
|
|
1831
1837
|
}
|
|
1832
1838
|
const finalBranch = await getCurrentBranch();
|
|
1833
1839
|
if (finalBranch && protectedBranches.has(finalBranch)) {
|
|
@@ -2069,7 +2075,7 @@ ${pc6.bold("Changed files:")}`);
|
|
|
2069
2075
|
error(`Failed to commit: ${result.stderr}`);
|
|
2070
2076
|
process.exit(1);
|
|
2071
2077
|
}
|
|
2072
|
-
success(
|
|
2078
|
+
success(`Committed: ${pc6.bold(finalMessage)}`);
|
|
2073
2079
|
}
|
|
2074
2080
|
});
|
|
2075
2081
|
async function runGroupCommit(model, config) {
|
|
@@ -2176,7 +2182,7 @@ ${pc6.bold(`AI suggested ${validGroups.length} commit group(s):`)}
|
|
|
2176
2182
|
continue;
|
|
2177
2183
|
}
|
|
2178
2184
|
committed++;
|
|
2179
|
-
success(
|
|
2185
|
+
success(`Committed group ${i + 1}: ${pc6.bold(group.message)}`);
|
|
2180
2186
|
}
|
|
2181
2187
|
} else {
|
|
2182
2188
|
for (let i = 0;i < validGroups.length; i++) {
|
|
@@ -2247,7 +2253,7 @@ ${pc6.bold(`AI suggested ${validGroups.length} commit group(s):`)}
|
|
|
2247
2253
|
continue;
|
|
2248
2254
|
}
|
|
2249
2255
|
committed++;
|
|
2250
|
-
success(
|
|
2256
|
+
success(`Committed group ${i + 1}: ${pc6.bold(message)}`);
|
|
2251
2257
|
actionDone = true;
|
|
2252
2258
|
}
|
|
2253
2259
|
}
|
|
@@ -2255,8 +2261,8 @@ ${pc6.bold(`AI suggested ${validGroups.length} commit group(s):`)}
|
|
|
2255
2261
|
if (committed === 0) {
|
|
2256
2262
|
warn("No groups were committed.");
|
|
2257
2263
|
} else {
|
|
2258
|
-
|
|
2259
|
-
|
|
2264
|
+
console.log();
|
|
2265
|
+
success(`${committed} of ${validGroups.length} group(s) committed successfully.`, "\uD83C\uDF89");
|
|
2260
2266
|
}
|
|
2261
2267
|
process.exit(0);
|
|
2262
2268
|
}
|
|
@@ -2268,7 +2274,7 @@ import pc7 from "picocolors";
|
|
|
2268
2274
|
// package.json
|
|
2269
2275
|
var package_default = {
|
|
2270
2276
|
name: "contribute-now",
|
|
2271
|
-
version: "0.6.
|
|
2277
|
+
version: "0.6.1-dev.4075d32",
|
|
2272
2278
|
description: "Developer CLI that automates git workflows — branching, syncing, committing, and PRs — with multi-workflow and commit convention support.",
|
|
2273
2279
|
type: "module",
|
|
2274
2280
|
bin: {
|
|
@@ -2731,7 +2737,7 @@ async function installHook() {
|
|
|
2731
2737
|
}
|
|
2732
2738
|
if (config.commitConvention === "none") {
|
|
2733
2739
|
warn('Commit convention is set to "none". No hook to install.');
|
|
2734
|
-
info("Change your convention with `contrib setup` first.");
|
|
2740
|
+
info("Change your convention with `contrib setup` first.", "");
|
|
2735
2741
|
process.exit(0);
|
|
2736
2742
|
}
|
|
2737
2743
|
const hookPath = getHookPath();
|
|
@@ -2751,8 +2757,8 @@ async function installHook() {
|
|
|
2751
2757
|
}
|
|
2752
2758
|
writeFileSync2(hookPath, generateHookScript(), { mode: 493 });
|
|
2753
2759
|
success(`commit-msg hook installed.`);
|
|
2754
|
-
info(`Convention: ${pc8.bold(CONVENTION_LABELS[config.commitConvention])}
|
|
2755
|
-
info(`Path: ${pc8.dim(hookPath)}
|
|
2760
|
+
info(`Convention: ${pc8.bold(CONVENTION_LABELS[config.commitConvention])}`, "");
|
|
2761
|
+
info(`Path: ${pc8.dim(hookPath)}`, "");
|
|
2756
2762
|
warn("Note: hooks can be bypassed with `git commit --no-verify`.");
|
|
2757
2763
|
}
|
|
2758
2764
|
async function uninstallHook() {
|
|
@@ -3169,7 +3175,7 @@ async function handleSave(message) {
|
|
|
3169
3175
|
return;
|
|
3170
3176
|
}
|
|
3171
3177
|
success(`Saved: ${pc10.dim(label)}`);
|
|
3172
|
-
info(`Use ${pc10.bold("contrib save --restore")} to bring them back
|
|
3178
|
+
info(`Use ${pc10.bold("contrib save --restore")} to bring them back.`, "");
|
|
3173
3179
|
}
|
|
3174
3180
|
async function handleRestore() {
|
|
3175
3181
|
heading("\uD83D\uDCBE contrib save --restore");
|
|
@@ -3214,8 +3220,8 @@ async function handleList() {
|
|
|
3214
3220
|
console.log(` ${idx} ${msg}`);
|
|
3215
3221
|
}
|
|
3216
3222
|
console.log();
|
|
3217
|
-
info(`Use ${pc10.bold("contrib save --restore")} to bring changes back
|
|
3218
|
-
info(`Use ${pc10.bold("contrib save --drop")} to discard saved changes
|
|
3223
|
+
info(`Use ${pc10.bold("contrib save --restore")} to bring changes back.`, "");
|
|
3224
|
+
info(`Use ${pc10.bold("contrib save --drop")} to discard saved changes.`, "");
|
|
3219
3225
|
}
|
|
3220
3226
|
async function handleDrop() {
|
|
3221
3227
|
heading("\uD83D\uDCBE contrib save --drop");
|
|
@@ -3425,7 +3431,7 @@ var setup_default = defineCommand8({
|
|
|
3425
3431
|
success(`Added remote ${pc11.bold(upstreamRemote)} → ${upstreamUrl}`);
|
|
3426
3432
|
} else {
|
|
3427
3433
|
error("An upstream remote URL is required for contributors.");
|
|
3428
|
-
info("Add it manually: git remote add upstream <url>");
|
|
3434
|
+
info("Add it manually: git remote add upstream <url>", "");
|
|
3429
3435
|
process.exit(1);
|
|
3430
3436
|
}
|
|
3431
3437
|
}
|
|
@@ -3441,9 +3447,9 @@ var setup_default = defineCommand8({
|
|
|
3441
3447
|
commitConvention
|
|
3442
3448
|
};
|
|
3443
3449
|
writeConfig(config);
|
|
3444
|
-
success(
|
|
3450
|
+
success(`Config written to .contributerc.json`);
|
|
3445
3451
|
const syncRemote = config.role === "contributor" ? config.upstream : config.origin;
|
|
3446
|
-
info(`Fetching ${pc11.bold(syncRemote)} to verify branch configuration
|
|
3452
|
+
info(`Fetching ${pc11.bold(syncRemote)} to verify branch configuration...`, "");
|
|
3447
3453
|
await fetchRemote(syncRemote);
|
|
3448
3454
|
const mainRef = `${syncRemote}/${config.mainBranch}`;
|
|
3449
3455
|
if (!await refExists(mainRef)) {
|
|
@@ -3565,7 +3571,7 @@ var start_default = defineCommand9({
|
|
|
3565
3571
|
info(`Creating branch: ${pc12.bold(branchName)}`);
|
|
3566
3572
|
if (await branchExists(branchName)) {
|
|
3567
3573
|
error(`Branch ${pc12.bold(branchName)} already exists.`);
|
|
3568
|
-
info(` Use ${pc12.bold(`git checkout ${branchName}`)} to switch to it, or choose a different name
|
|
3574
|
+
info(` Use ${pc12.bold(`git checkout ${branchName}`)} to switch to it, or choose a different name.`, "");
|
|
3569
3575
|
process.exit(1);
|
|
3570
3576
|
}
|
|
3571
3577
|
await fetchRemote(syncSource.remote);
|
|
@@ -3593,11 +3599,11 @@ var start_default = defineCommand9({
|
|
|
3593
3599
|
error(`Failed to create branch: ${result2.stderr}`);
|
|
3594
3600
|
process.exit(1);
|
|
3595
3601
|
}
|
|
3596
|
-
success(
|
|
3602
|
+
success(`Created ${pc12.bold(branchName)} from ${pc12.bold(syncSource.ref)}`);
|
|
3597
3603
|
return;
|
|
3598
3604
|
}
|
|
3599
3605
|
error(`Failed to update ${pc12.bold(baseBranch)}: ${updateResult.stderr}`);
|
|
3600
|
-
info("Make sure your base branch exists locally or the remote ref is available.");
|
|
3606
|
+
info("Make sure your base branch exists locally or the remote ref is available.", "");
|
|
3601
3607
|
process.exit(1);
|
|
3602
3608
|
}
|
|
3603
3609
|
const result = await createBranch(branchName, baseBranch);
|
|
@@ -3605,7 +3611,7 @@ var start_default = defineCommand9({
|
|
|
3605
3611
|
error(`Failed to create branch: ${result.stderr}`);
|
|
3606
3612
|
process.exit(1);
|
|
3607
3613
|
}
|
|
3608
|
-
success(
|
|
3614
|
+
success(`Created ${pc12.bold(branchName)} from latest ${pc12.bold(baseBranch)}`);
|
|
3609
3615
|
}
|
|
3610
3616
|
});
|
|
3611
3617
|
|
|
@@ -3668,6 +3674,51 @@ var status_default = defineCommand10({
|
|
|
3668
3674
|
} else if (currentBranch) {
|
|
3669
3675
|
console.log(pc13.dim(` (on ${pc13.bold(currentBranch)} branch)`));
|
|
3670
3676
|
}
|
|
3677
|
+
let branchesAligned = true;
|
|
3678
|
+
{
|
|
3679
|
+
const alignRefs = [];
|
|
3680
|
+
const devRemote = isContributor ? upstream : origin;
|
|
3681
|
+
const hashResults = await Promise.all([
|
|
3682
|
+
getCommitHash(mainBranch).then((h) => ({ name: mainBranch, hash: h })),
|
|
3683
|
+
getCommitHash(`${origin}/${mainBranch}`).then((h) => ({ name: `${origin}/${mainBranch}`, hash: h })),
|
|
3684
|
+
...hasDevBranch(workflow) && config.devBranch ? [
|
|
3685
|
+
getCommitHash(config.devBranch).then((h) => ({ name: config.devBranch, hash: h })),
|
|
3686
|
+
getCommitHash(`${devRemote}/${config.devBranch}`).then((h) => ({
|
|
3687
|
+
name: `${devRemote}/${config.devBranch}`,
|
|
3688
|
+
hash: h
|
|
3689
|
+
}))
|
|
3690
|
+
] : []
|
|
3691
|
+
]);
|
|
3692
|
+
for (const { name, hash } of hashResults) {
|
|
3693
|
+
if (hash)
|
|
3694
|
+
alignRefs.push({ name, hash });
|
|
3695
|
+
}
|
|
3696
|
+
if (alignRefs.length > 1) {
|
|
3697
|
+
const groups = new Map;
|
|
3698
|
+
for (const { name, hash } of alignRefs) {
|
|
3699
|
+
if (!groups.has(hash))
|
|
3700
|
+
groups.set(hash, []);
|
|
3701
|
+
groups.get(hash).push(name);
|
|
3702
|
+
}
|
|
3703
|
+
branchesAligned = groups.size === 1;
|
|
3704
|
+
console.log();
|
|
3705
|
+
console.log(` ${pc13.bold("\uD83D\uDD17 Branch Alignment")}`);
|
|
3706
|
+
for (const [hash, names] of groups) {
|
|
3707
|
+
const short = hash.slice(0, 7);
|
|
3708
|
+
const nameStr = names.map((n) => pc13.bold(n)).join(pc13.dim(" · "));
|
|
3709
|
+
console.log(` ${pc13.yellow(short)} ${pc13.dim("──")} ${nameStr}`);
|
|
3710
|
+
const subject = await getCommitSubject(hash);
|
|
3711
|
+
if (subject) {
|
|
3712
|
+
console.log(` ${pc13.dim(subject)}`);
|
|
3713
|
+
}
|
|
3714
|
+
}
|
|
3715
|
+
if (branchesAligned) {
|
|
3716
|
+
console.log(` ${pc13.green("✓")} ${pc13.green("All branches aligned")} ${pc13.dim("— ready to start")}`);
|
|
3717
|
+
} else {
|
|
3718
|
+
console.log(` ${pc13.yellow("⚠")} ${pc13.yellow("Branches are not fully aligned")}`);
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3671
3722
|
const hasFiles = fileStatus.staged.length > 0 || fileStatus.modified.length > 0 || fileStatus.untracked.length > 0;
|
|
3672
3723
|
if (hasFiles) {
|
|
3673
3724
|
console.log();
|
|
@@ -3693,6 +3744,9 @@ var status_default = defineCommand10({
|
|
|
3693
3744
|
console.log(` ${pc13.green("✓")} ${pc13.dim("Working tree clean")}`);
|
|
3694
3745
|
}
|
|
3695
3746
|
const tips = [];
|
|
3747
|
+
if (!branchesAligned) {
|
|
3748
|
+
tips.push(`Run ${pc13.bold("contrib sync")} to align your local branches with the remote`);
|
|
3749
|
+
}
|
|
3696
3750
|
if (fileStatus.staged.length > 0) {
|
|
3697
3751
|
tips.push(`Run ${pc13.bold("contrib commit")} to commit staged changes`);
|
|
3698
3752
|
}
|
|
@@ -3870,8 +3924,8 @@ async function performSquashMerge(origin, baseBranch, featureBranch, options) {
|
|
|
3870
3924
|
warn(`Could not delete remote branch: ${delRemote.stderr.trim()}`);
|
|
3871
3925
|
}
|
|
3872
3926
|
}
|
|
3873
|
-
success(
|
|
3874
|
-
info(`Run ${pc14.bold("contrib start")} to begin a new feature
|
|
3927
|
+
success(`Squash merged ${pc14.bold(featureBranch)} into ${pc14.bold(baseBranch)} and pushed.`);
|
|
3928
|
+
info(`Run ${pc14.bold("contrib start")} to begin a new feature.`, "");
|
|
3875
3929
|
}
|
|
3876
3930
|
var submit_default = defineCommand11({
|
|
3877
3931
|
meta: {
|
|
@@ -3924,7 +3978,7 @@ var submit_default = defineCommand11({
|
|
|
3924
3978
|
const hasAnything = hasCommits || dirty;
|
|
3925
3979
|
if (!hasAnything) {
|
|
3926
3980
|
error("No local changes or commits to move. Switch to a feature branch first.");
|
|
3927
|
-
info(` Run ${pc14.bold("contrib start")} to create a new feature branch
|
|
3981
|
+
info(` Run ${pc14.bold("contrib start")} to create a new feature branch.`, "");
|
|
3928
3982
|
process.exit(1);
|
|
3929
3983
|
}
|
|
3930
3984
|
if (hasCommits) {
|
|
@@ -3983,10 +4037,10 @@ var submit_default = defineCommand11({
|
|
|
3983
4037
|
}
|
|
3984
4038
|
success(`Created ${pc14.bold(newBranchName)} with your changes.`);
|
|
3985
4039
|
await updateLocalBranch(currentBranch, remoteRef);
|
|
3986
|
-
info(`Reset ${pc14.bold(currentBranch)} back to ${pc14.bold(remoteRef)} — no damage done
|
|
4040
|
+
info(`Reset ${pc14.bold(currentBranch)} back to ${pc14.bold(remoteRef)} — no damage done.`, "");
|
|
3987
4041
|
console.log();
|
|
3988
4042
|
success(`You're now on ${pc14.bold(newBranchName)} with all your work intact.`);
|
|
3989
|
-
info(`Run ${pc14.bold("contrib submit")} again to push and create your PR
|
|
4043
|
+
info(`Run ${pc14.bold("contrib submit")} again to push and create your PR.`, "");
|
|
3990
4044
|
return;
|
|
3991
4045
|
}
|
|
3992
4046
|
heading("\uD83D\uDE80 contrib submit");
|
|
@@ -4064,11 +4118,11 @@ var submit_default = defineCommand11({
|
|
|
4064
4118
|
}
|
|
4065
4119
|
if (rebaseResult.exitCode !== 0) {
|
|
4066
4120
|
warn("Rebase encountered conflicts. Resolve them manually, then run:");
|
|
4067
|
-
info(` ${pc14.bold("git rebase --continue")}
|
|
4121
|
+
info(` ${pc14.bold("git rebase --continue")}`, "");
|
|
4068
4122
|
} else {
|
|
4069
4123
|
success(`Rebased ${pc14.bold(newBranchName)} onto ${pc14.bold(syncSource2.ref)}.`);
|
|
4070
4124
|
}
|
|
4071
|
-
info(`All your changes are preserved. Run ${pc14.bold("contrib submit")} when ready to create a new PR
|
|
4125
|
+
info(`All your changes are preserved. Run ${pc14.bold("contrib submit")} when ready to create a new PR.`, "");
|
|
4072
4126
|
return;
|
|
4073
4127
|
}
|
|
4074
4128
|
warn("Discarding local changes...");
|
|
@@ -4105,8 +4159,8 @@ var submit_default = defineCommand11({
|
|
|
4105
4159
|
error(`Failed to push: ${pushResult2.stderr}`);
|
|
4106
4160
|
if (pushResult2.stderr.includes("rejected") || pushResult2.stderr.includes("non-fast-forward")) {
|
|
4107
4161
|
warn("The remote branch has diverged. Try:");
|
|
4108
|
-
info(` git pull --rebase ${origin} ${currentBranch}
|
|
4109
|
-
info(" Then run `contrib submit` again.");
|
|
4162
|
+
info(` git pull --rebase ${origin} ${currentBranch}`, "");
|
|
4163
|
+
info(" Then run `contrib submit` again.", "");
|
|
4110
4164
|
}
|
|
4111
4165
|
process.exit(1);
|
|
4112
4166
|
}
|
|
@@ -4142,22 +4196,39 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4142
4196
|
warn(`AI unavailable: ${copilotError}`);
|
|
4143
4197
|
}
|
|
4144
4198
|
}
|
|
4145
|
-
if (!args["no-ai"]) {
|
|
4146
|
-
await tryGenerateAI();
|
|
4147
|
-
}
|
|
4148
4199
|
const CANCEL = "Cancel";
|
|
4149
4200
|
const SQUASH_LOCAL = `Squash merge to ${baseBranch} locally (no PR)`;
|
|
4150
4201
|
const REGENERATE = "Regenerate AI description";
|
|
4151
4202
|
let submitAction = "cancel";
|
|
4152
4203
|
const isMaintainer = config.role === "maintainer";
|
|
4204
|
+
if (isMaintainer) {
|
|
4205
|
+
const maintainerChoice = await selectPrompt("How would you like to submit your changes?", ["Create a PR", SQUASH_LOCAL, CANCEL]);
|
|
4206
|
+
if (maintainerChoice === CANCEL) {
|
|
4207
|
+
warn("Submit cancelled.");
|
|
4208
|
+
return;
|
|
4209
|
+
}
|
|
4210
|
+
if (maintainerChoice === SQUASH_LOCAL) {
|
|
4211
|
+
await performSquashMerge(origin, baseBranch, currentBranch, {
|
|
4212
|
+
model: args.model,
|
|
4213
|
+
convention: config.commitConvention
|
|
4214
|
+
});
|
|
4215
|
+
return;
|
|
4216
|
+
}
|
|
4217
|
+
}
|
|
4218
|
+
if (!args["no-ai"]) {
|
|
4219
|
+
await tryGenerateAI();
|
|
4220
|
+
}
|
|
4153
4221
|
let actionResolved = false;
|
|
4154
4222
|
while (!actionResolved) {
|
|
4155
4223
|
if (prTitle && prBody) {
|
|
4156
|
-
const
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4224
|
+
const action = await selectPrompt("What would you like to do with the PR description?", [
|
|
4225
|
+
"Use AI description",
|
|
4226
|
+
"Edit title",
|
|
4227
|
+
"Write manually",
|
|
4228
|
+
"Use gh --fill (auto-fill from commits)",
|
|
4229
|
+
REGENERATE,
|
|
4230
|
+
CANCEL
|
|
4231
|
+
]);
|
|
4161
4232
|
if (action === CANCEL) {
|
|
4162
4233
|
submitAction = "cancel";
|
|
4163
4234
|
actionResolved = true;
|
|
@@ -4165,9 +4236,6 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4165
4236
|
prTitle = null;
|
|
4166
4237
|
prBody = null;
|
|
4167
4238
|
await tryGenerateAI();
|
|
4168
|
-
} else if (action === SQUASH_LOCAL) {
|
|
4169
|
-
submitAction = "squash";
|
|
4170
|
-
actionResolved = true;
|
|
4171
4239
|
} else if (action === "Use AI description") {
|
|
4172
4240
|
submitAction = "create-pr";
|
|
4173
4241
|
actionResolved = true;
|
|
@@ -4186,8 +4254,6 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4186
4254
|
}
|
|
4187
4255
|
} else {
|
|
4188
4256
|
const choices = [];
|
|
4189
|
-
if (isMaintainer)
|
|
4190
|
-
choices.push(SQUASH_LOCAL);
|
|
4191
4257
|
if (!args["no-ai"])
|
|
4192
4258
|
choices.push(REGENERATE);
|
|
4193
4259
|
choices.push("Write title & body manually", "Use gh --fill (auto-fill from commits)", CANCEL);
|
|
@@ -4197,9 +4263,6 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4197
4263
|
actionResolved = true;
|
|
4198
4264
|
} else if (action === REGENERATE) {
|
|
4199
4265
|
await tryGenerateAI();
|
|
4200
|
-
} else if (action === SQUASH_LOCAL) {
|
|
4201
|
-
submitAction = "squash";
|
|
4202
|
-
actionResolved = true;
|
|
4203
4266
|
} else if (action === "Write title & body manually") {
|
|
4204
4267
|
prTitle = await inputPrompt("PR title");
|
|
4205
4268
|
prBody = await inputPrompt("PR body (markdown)");
|
|
@@ -4215,23 +4278,16 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4215
4278
|
warn("Submit cancelled.");
|
|
4216
4279
|
return;
|
|
4217
4280
|
}
|
|
4218
|
-
if (submitAction === "squash") {
|
|
4219
|
-
await performSquashMerge(origin, baseBranch, currentBranch, {
|
|
4220
|
-
model: args.model,
|
|
4221
|
-
convention: config.commitConvention
|
|
4222
|
-
});
|
|
4223
|
-
return;
|
|
4224
|
-
}
|
|
4225
4281
|
info(`Pushing ${pc14.bold(currentBranch)} to ${origin}...`);
|
|
4226
4282
|
const pushResult = await pushSetUpstream(origin, currentBranch);
|
|
4227
4283
|
if (pushResult.exitCode !== 0) {
|
|
4228
4284
|
error(`Failed to push: ${pushResult.stderr}`);
|
|
4229
4285
|
if (pushResult.stderr.includes("rejected") || pushResult.stderr.includes("non-fast-forward")) {
|
|
4230
4286
|
warn("The remote branch has diverged. Try:");
|
|
4231
|
-
info(` git pull --rebase ${origin} ${currentBranch}
|
|
4232
|
-
info(" Then run `contrib submit` again.");
|
|
4233
|
-
info("If you need to force push (use with caution):");
|
|
4234
|
-
info(` git push --force-with-lease ${origin} ${currentBranch}
|
|
4287
|
+
info(` git pull --rebase ${origin} ${currentBranch}`, "");
|
|
4288
|
+
info(" Then run `contrib submit` again.", "");
|
|
4289
|
+
info("If you need to force push (use with caution):", "");
|
|
4290
|
+
info(` git push --force-with-lease ${origin} ${currentBranch}`, "");
|
|
4235
4291
|
}
|
|
4236
4292
|
process.exit(1);
|
|
4237
4293
|
}
|
|
@@ -4240,10 +4296,10 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4240
4296
|
if (repoInfo) {
|
|
4241
4297
|
const prUrl = `https://github.com/${repoInfo.owner}/${repoInfo.repo}/compare/${baseBranch}...${currentBranch}?expand=1`;
|
|
4242
4298
|
console.log();
|
|
4243
|
-
info("Create your PR manually:");
|
|
4299
|
+
info("Create your PR manually:", "");
|
|
4244
4300
|
console.log(` ${pc14.cyan(prUrl)}`);
|
|
4245
4301
|
} else {
|
|
4246
|
-
info("gh CLI not available. Create your PR manually on GitHub.");
|
|
4302
|
+
info("gh CLI not available. Create your PR manually on GitHub.", "");
|
|
4247
4303
|
}
|
|
4248
4304
|
return;
|
|
4249
4305
|
}
|
|
@@ -4253,7 +4309,7 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4253
4309
|
error(`Failed to create PR: ${fillResult.stderr}`);
|
|
4254
4310
|
process.exit(1);
|
|
4255
4311
|
}
|
|
4256
|
-
success(
|
|
4312
|
+
success(`PR created: ${fillResult.stdout.trim()}`);
|
|
4257
4313
|
return;
|
|
4258
4314
|
}
|
|
4259
4315
|
if (!prTitle) {
|
|
@@ -4270,7 +4326,7 @@ ${pc14.dim("AI body preview:")}`);
|
|
|
4270
4326
|
error(`Failed to create PR: ${prResult.stderr}`);
|
|
4271
4327
|
process.exit(1);
|
|
4272
4328
|
}
|
|
4273
|
-
success(
|
|
4329
|
+
success(`PR created: ${prResult.stdout.trim()}`);
|
|
4274
4330
|
}
|
|
4275
4331
|
});
|
|
4276
4332
|
|
|
@@ -4360,8 +4416,8 @@ var switch_default = defineCommand12({
|
|
|
4360
4416
|
process.exit(1);
|
|
4361
4417
|
}
|
|
4362
4418
|
success(`Switched to ${pc15.bold(targetBranch)}`);
|
|
4363
|
-
info(`Your changes from ${pc15.bold(currentBranch ?? "previous branch")} are saved
|
|
4364
|
-
info(`Use ${pc15.bold("contrib save --restore")} to bring them back
|
|
4419
|
+
info(`Your changes from ${pc15.bold(currentBranch ?? "previous branch")} are saved.`, "");
|
|
4420
|
+
info(`Use ${pc15.bold("contrib save --restore")} to bring them back.`, "");
|
|
4365
4421
|
return;
|
|
4366
4422
|
}
|
|
4367
4423
|
const result = await checkoutBranch(targetBranch);
|
|
@@ -4428,8 +4484,8 @@ var sync_default = defineCommand13({
|
|
|
4428
4484
|
}
|
|
4429
4485
|
if (!await refExists(syncSource.ref)) {
|
|
4430
4486
|
error(`Remote ref ${pc16.bold(syncSource.ref)} does not exist.`);
|
|
4431
|
-
info("This can happen if the branch was renamed or deleted on the remote.");
|
|
4432
|
-
info(`Check your config: the base branch may need updating via ${pc16.bold("contrib setup")}
|
|
4487
|
+
info("This can happen if the branch was renamed or deleted on the remote.", "");
|
|
4488
|
+
info(`Check your config: the base branch may need updating via ${pc16.bold("contrib setup")}.`, "");
|
|
4433
4489
|
process.exit(1);
|
|
4434
4490
|
}
|
|
4435
4491
|
let allowMergeCommit = false;
|
|
@@ -4506,10 +4562,10 @@ var sync_default = defineCommand13({
|
|
|
4506
4562
|
const remoteRef = syncSource.ref;
|
|
4507
4563
|
await updateLocalBranch(baseBranch, remoteRef);
|
|
4508
4564
|
success(`Reset ${pc16.bold(baseBranch)} to ${pc16.bold(remoteRef)}.`);
|
|
4509
|
-
success(
|
|
4565
|
+
success(`${pc16.bold(baseBranch)} is now in sync with ${syncSource.ref}`);
|
|
4510
4566
|
console.log();
|
|
4511
|
-
info(`Your commits are safe on ${pc16.bold(newBranchName)}
|
|
4512
|
-
info(`Run ${pc16.bold(`git checkout ${newBranchName}`)} then ${pc16.bold("contrib update")} to rebase onto the synced ${pc16.bold(baseBranch)}
|
|
4567
|
+
info(`Your commits are safe on ${pc16.bold(newBranchName)}.`, "");
|
|
4568
|
+
info(`Run ${pc16.bold(`git checkout ${newBranchName}`)} then ${pc16.bold("contrib update")} to rebase onto the synced ${pc16.bold(baseBranch)}.`, "");
|
|
4513
4569
|
return;
|
|
4514
4570
|
}
|
|
4515
4571
|
allowMergeCommit = true;
|
|
@@ -4532,11 +4588,11 @@ var sync_default = defineCommand13({
|
|
|
4532
4588
|
error(`Pull failed: ${pullResult.stderr.trim()}`);
|
|
4533
4589
|
} else {
|
|
4534
4590
|
error(`Fast-forward pull failed. Your local ${pc16.bold(baseBranch)} may have diverged.`);
|
|
4535
|
-
info(`Use ${pc16.bold("contrib sync")} again and choose "Move my commits to a new feature branch" to fix this
|
|
4591
|
+
info(`Use ${pc16.bold("contrib sync")} again and choose "Move my commits to a new feature branch" to fix this.`, "");
|
|
4536
4592
|
}
|
|
4537
4593
|
process.exit(1);
|
|
4538
4594
|
}
|
|
4539
|
-
success(
|
|
4595
|
+
success(`${baseBranch} is now in sync with ${syncSource.ref}`);
|
|
4540
4596
|
if (hasDevBranch(workflow) && role === "maintainer") {
|
|
4541
4597
|
const mainDiv = await getDivergence(config.mainBranch, `${origin}/${config.mainBranch}`);
|
|
4542
4598
|
if (mainDiv.behind > 0) {
|
|
@@ -4545,7 +4601,7 @@ var sync_default = defineCommand13({
|
|
|
4545
4601
|
if (mainCoResult.exitCode === 0) {
|
|
4546
4602
|
const mainPullResult = await pullFastForwardOnly(origin, config.mainBranch);
|
|
4547
4603
|
if (mainPullResult.exitCode === 0) {
|
|
4548
|
-
success(
|
|
4604
|
+
success(`${config.mainBranch} is now in sync with ${origin}/${config.mainBranch}`);
|
|
4549
4605
|
}
|
|
4550
4606
|
}
|
|
4551
4607
|
await checkoutBranch(baseBranch);
|
|
@@ -4660,10 +4716,10 @@ var update_default = defineCommand14({
|
|
|
4660
4716
|
}
|
|
4661
4717
|
success(`Created ${pc17.bold(newBranchName)} with your changes.`);
|
|
4662
4718
|
await updateLocalBranch(currentBranch, remoteRef);
|
|
4663
|
-
info(`Reset ${pc17.bold(currentBranch)} back to ${pc17.bold(remoteRef)} — no damage done
|
|
4719
|
+
info(`Reset ${pc17.bold(currentBranch)} back to ${pc17.bold(remoteRef)} — no damage done.`, "");
|
|
4664
4720
|
console.log();
|
|
4665
4721
|
success(`You're now on ${pc17.bold(newBranchName)} with all your work intact.`);
|
|
4666
|
-
info(`Run ${pc17.bold("contrib update")} again to rebase onto latest ${pc17.bold(baseBranch)}
|
|
4722
|
+
info(`Run ${pc17.bold("contrib update")} again to rebase onto latest ${pc17.bold(baseBranch)}.`, "");
|
|
4667
4723
|
return;
|
|
4668
4724
|
}
|
|
4669
4725
|
if (await hasUncommittedChanges()) {
|
|
@@ -4674,7 +4730,7 @@ var update_default = defineCommand14({
|
|
|
4674
4730
|
const mergedPR = await getMergedPRForBranch(currentBranch);
|
|
4675
4731
|
if (mergedPR) {
|
|
4676
4732
|
warn(`PR #${mergedPR.number} (${pc17.bold(mergedPR.title)}) has already been merged.`);
|
|
4677
|
-
info(`Link: ${pc17.underline(mergedPR.url)}
|
|
4733
|
+
info(`Link: ${pc17.underline(mergedPR.url)}`, "");
|
|
4678
4734
|
const localWork = await hasLocalWork(syncSource.remote, currentBranch);
|
|
4679
4735
|
const hasWork = localWork.uncommitted || localWork.unpushedCommits > 0;
|
|
4680
4736
|
if (hasWork) {
|
|
@@ -4741,11 +4797,11 @@ var update_default = defineCommand14({
|
|
|
4741
4797
|
}
|
|
4742
4798
|
if (rebaseResult2.exitCode !== 0) {
|
|
4743
4799
|
warn("Rebase encountered conflicts. Resolve them manually, then run:");
|
|
4744
|
-
info(` ${pc17.bold("git rebase --continue")}
|
|
4800
|
+
info(` ${pc17.bold("git rebase --continue")}`, "");
|
|
4745
4801
|
} else {
|
|
4746
4802
|
success(`Rebased ${pc17.bold(newBranchName)} onto ${pc17.bold(syncSource.ref)}.`);
|
|
4747
4803
|
}
|
|
4748
|
-
info(`All your changes are preserved. Run ${pc17.bold("contrib submit")} when ready to create a new PR
|
|
4804
|
+
info(`All your changes are preserved. Run ${pc17.bold("contrib submit")} when ready to create a new PR.`, "");
|
|
4749
4805
|
return;
|
|
4750
4806
|
}
|
|
4751
4807
|
warn("Discarding local changes...");
|
|
@@ -4762,7 +4818,7 @@ var update_default = defineCommand14({
|
|
|
4762
4818
|
info(`Deleting stale branch ${pc17.bold(currentBranch)}...`);
|
|
4763
4819
|
await forceDeleteBranch(currentBranch);
|
|
4764
4820
|
success(`Deleted ${pc17.bold(currentBranch)}.`);
|
|
4765
|
-
info(`Run ${pc17.bold("contrib start")} to begin a new feature branch
|
|
4821
|
+
info(`Run ${pc17.bold("contrib start")} to begin a new feature branch.`, "");
|
|
4766
4822
|
return;
|
|
4767
4823
|
}
|
|
4768
4824
|
info(`Updating ${pc17.bold(currentBranch)} with latest ${pc17.bold(baseBranch)}...`);
|
|
@@ -4823,7 +4879,7 @@ ${pc17.bold("\uD83D\uDCA1 AI Conflict Resolution Guidance:")}`);
|
|
|
4823
4879
|
console.log(` Or abort: ${pc17.cyan("git rebase --abort")}`);
|
|
4824
4880
|
process.exit(1);
|
|
4825
4881
|
}
|
|
4826
|
-
success(
|
|
4882
|
+
success(`${pc17.bold(currentBranch)} has been rebased onto latest ${pc17.bold(baseBranch)}`);
|
|
4827
4883
|
}
|
|
4828
4884
|
});
|
|
4829
4885
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "contribute-now",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1-dev.4075d32",
|
|
4
4
|
"description": "Developer CLI that automates git workflows — branching, syncing, committing, and PRs — with multi-workflow and commit convention support.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|