@markjaquith/agency 1.9.2 → 1.9.4
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/package.json +1 -1
- package/src/commands/emit.test.ts +44 -0
- package/src/commands/emit.ts +43 -3
- package/src/commands/push.test.ts +33 -0
- package/src/commands/push.ts +29 -43
package/package.json
CHANGED
|
@@ -125,6 +125,50 @@ describe("emit command", () => {
|
|
|
125
125
|
expect(currentBranch).toBe("agency--feature")
|
|
126
126
|
})
|
|
127
127
|
|
|
128
|
+
test("sets emit branch upstream when remote branch exists", async () => {
|
|
129
|
+
await checkoutBranch(tempDir, "main")
|
|
130
|
+
await createBranch(tempDir, "agency--feature")
|
|
131
|
+
await Bun.write(
|
|
132
|
+
join(tempDir, "agency.json"),
|
|
133
|
+
JSON.stringify({
|
|
134
|
+
version: 1,
|
|
135
|
+
injectedFiles: ["AGENTS.md"],
|
|
136
|
+
template: "test",
|
|
137
|
+
createdAt: new Date().toISOString(),
|
|
138
|
+
}),
|
|
139
|
+
)
|
|
140
|
+
await addAndCommit(tempDir, "agency.json", "Feature commit")
|
|
141
|
+
|
|
142
|
+
await getGitOutput(tempDir, [
|
|
143
|
+
"update-ref",
|
|
144
|
+
"refs/remotes/origin/feature",
|
|
145
|
+
"HEAD",
|
|
146
|
+
])
|
|
147
|
+
|
|
148
|
+
await runTestEffect(emit({ silent: true, skipFilter: true }))
|
|
149
|
+
|
|
150
|
+
const remote = await getGitOutput(tempDir, [
|
|
151
|
+
"config",
|
|
152
|
+
"--get",
|
|
153
|
+
"branch.feature.remote",
|
|
154
|
+
])
|
|
155
|
+
const merge = await getGitOutput(tempDir, [
|
|
156
|
+
"config",
|
|
157
|
+
"--get",
|
|
158
|
+
"branch.feature.merge",
|
|
159
|
+
])
|
|
160
|
+
expect(remote.trim()).toBe("origin")
|
|
161
|
+
expect(merge.trim()).toBe("refs/heads/feature")
|
|
162
|
+
|
|
163
|
+
await checkoutBranch(tempDir, "feature")
|
|
164
|
+
const pushRef = await getGitOutput(tempDir, [
|
|
165
|
+
"rev-parse",
|
|
166
|
+
"--abbrev-ref",
|
|
167
|
+
"@{push}",
|
|
168
|
+
])
|
|
169
|
+
expect(pushRef.trim()).toBe("origin/feature")
|
|
170
|
+
})
|
|
171
|
+
|
|
128
172
|
test("creates emit branch with custom name", async () => {
|
|
129
173
|
await createBranch(tempDir, "agency--feature")
|
|
130
174
|
await createCommit(tempDir, "Feature commit")
|
package/src/commands/emit.ts
CHANGED
|
@@ -158,9 +158,7 @@ export const emitCore = (gitRoot: string, options: EmitOptions) =>
|
|
|
158
158
|
)
|
|
159
159
|
branchExisted = existed
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
yield* git.unsetGitConfig(`branch.${emitBranchName}.remote`, gitRoot)
|
|
163
|
-
yield* git.unsetGitConfig(`branch.${emitBranchName}.merge`, gitRoot)
|
|
161
|
+
yield* configureEmitBranchTracking(gitRoot, emitBranchName, verboseLog)
|
|
164
162
|
})
|
|
165
163
|
|
|
166
164
|
yield* withSpinner(createBranch, {
|
|
@@ -435,6 +433,48 @@ const getFilterRepoStateDir = (gitRoot: string) =>
|
|
|
435
433
|
return resolveGitInternalPath(gitRoot, gitPath)
|
|
436
434
|
})
|
|
437
435
|
|
|
436
|
+
const configureEmitBranchTracking = (
|
|
437
|
+
gitRoot: string,
|
|
438
|
+
emitBranchName: string,
|
|
439
|
+
verboseLog: (message: string) => void,
|
|
440
|
+
) =>
|
|
441
|
+
Effect.gen(function* () {
|
|
442
|
+
const git = yield* GitService
|
|
443
|
+
const remote = yield* git.resolveRemote(gitRoot).pipe(Effect.option)
|
|
444
|
+
|
|
445
|
+
if (remote._tag === "None") {
|
|
446
|
+
yield* git.unsetGitConfig(`branch.${emitBranchName}.remote`, gitRoot)
|
|
447
|
+
yield* git.unsetGitConfig(`branch.${emitBranchName}.merge`, gitRoot)
|
|
448
|
+
return
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
const remoteBranch = `${remote.value}/${emitBranchName}`
|
|
452
|
+
const remoteBranchExists = yield* git.branchExists(gitRoot, remoteBranch)
|
|
453
|
+
|
|
454
|
+
if (!remoteBranchExists) {
|
|
455
|
+
yield* git.unsetGitConfig(`branch.${emitBranchName}.remote`, gitRoot)
|
|
456
|
+
yield* git.unsetGitConfig(`branch.${emitBranchName}.merge`, gitRoot)
|
|
457
|
+
verboseLog(
|
|
458
|
+
`No existing remote branch ${highlight.branch(remoteBranch)}; leaving ${highlight.branch(emitBranchName)} without upstream`,
|
|
459
|
+
)
|
|
460
|
+
return
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
yield* git.setGitConfig(
|
|
464
|
+
`branch.${emitBranchName}.remote`,
|
|
465
|
+
remote.value,
|
|
466
|
+
gitRoot,
|
|
467
|
+
)
|
|
468
|
+
yield* git.setGitConfig(
|
|
469
|
+
`branch.${emitBranchName}.merge`,
|
|
470
|
+
`refs/heads/${emitBranchName}`,
|
|
471
|
+
gitRoot,
|
|
472
|
+
)
|
|
473
|
+
verboseLog(
|
|
474
|
+
`Set ${highlight.branch(emitBranchName)} upstream to ${highlight.branch(remoteBranch)}`,
|
|
475
|
+
)
|
|
476
|
+
})
|
|
477
|
+
|
|
438
478
|
/**
|
|
439
479
|
* Find the best fork point by checking both local and remote tracking branches.
|
|
440
480
|
*
|
|
@@ -115,6 +115,39 @@ describe("push command", () => {
|
|
|
115
115
|
expect(remoteBranches).toContain("feature")
|
|
116
116
|
})
|
|
117
117
|
|
|
118
|
+
test("forwards verbose output from emit step", async () => {
|
|
119
|
+
const originalLog = console.log
|
|
120
|
+
const logMessages: string[] = []
|
|
121
|
+
console.log = (msg: string) => {
|
|
122
|
+
logMessages.push(msg)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
await runTestEffect(
|
|
127
|
+
push({
|
|
128
|
+
baseBranch: "main",
|
|
129
|
+
verbose: true,
|
|
130
|
+
skipFilter: true,
|
|
131
|
+
}),
|
|
132
|
+
)
|
|
133
|
+
} finally {
|
|
134
|
+
console.log = originalLog
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
expect(logMessages).toContain("Step 1: Emitting...")
|
|
138
|
+
expect(
|
|
139
|
+
logMessages.some(
|
|
140
|
+
(msg) => msg.includes("Using base branch:") && msg.includes("main"),
|
|
141
|
+
),
|
|
142
|
+
).toBe(true)
|
|
143
|
+
expect(
|
|
144
|
+
logMessages.some((msg) =>
|
|
145
|
+
msg.includes("Skipping git-filter-repo (skipFilter=true)"),
|
|
146
|
+
),
|
|
147
|
+
).toBe(true)
|
|
148
|
+
expect(logMessages.some((msg) => msg.includes("Emitted"))).toBe(true)
|
|
149
|
+
})
|
|
150
|
+
|
|
118
151
|
test("works with custom branch name", async () => {
|
|
119
152
|
await runTestEffect(
|
|
120
153
|
push({
|
package/src/commands/push.ts
CHANGED
|
@@ -122,41 +122,36 @@ const pushCore = (gitRoot: string, options: PushOptions) =>
|
|
|
122
122
|
verboseLog(`Starting push workflow from ${highlight.branch(sourceBranch)}`)
|
|
123
123
|
|
|
124
124
|
// Step 1: Create emit branch (agency emit)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
return yield* Effect.fail(
|
|
153
|
-
new Error(`Failed to create emit branch: ${message}`),
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
emitHadIgnorableFailure = true
|
|
158
|
-
verboseLog("Emit reported existing branch; continuing")
|
|
125
|
+
verboseLog("Step 1: Emitting...")
|
|
126
|
+
// Use the emit command for the entire emit step so push and emit stay in sync.
|
|
127
|
+
const prEffectWithOptions = emit({
|
|
128
|
+
baseBranch: options.baseBranch,
|
|
129
|
+
emit: options.emit || options.branch,
|
|
130
|
+
silent: options.silent,
|
|
131
|
+
force: options.force,
|
|
132
|
+
verbose: options.verbose,
|
|
133
|
+
skipFilter: options.skipFilter,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
const prResult = yield* Effect.either(prEffectWithOptions)
|
|
137
|
+
if (Either.isLeft(prResult)) {
|
|
138
|
+
const error =
|
|
139
|
+
prResult.left instanceof Error
|
|
140
|
+
? prResult.left
|
|
141
|
+
: new Error(String(prResult.left))
|
|
142
|
+
const message = error.message || ""
|
|
143
|
+
const ignorable =
|
|
144
|
+
message === "" ||
|
|
145
|
+
message.includes("already exists") ||
|
|
146
|
+
message.includes("check if branch exists")
|
|
147
|
+
|
|
148
|
+
if (!ignorable) {
|
|
149
|
+
return yield* Effect.fail(
|
|
150
|
+
new Error(`Failed to create emit branch: ${message}`),
|
|
151
|
+
)
|
|
159
152
|
}
|
|
153
|
+
|
|
154
|
+
verboseLog("Emit reported existing branch; continuing")
|
|
160
155
|
}
|
|
161
156
|
|
|
162
157
|
// Compute the emit branch name (emit() command now stays on source branch)
|
|
@@ -164,15 +159,6 @@ const pushCore = (gitRoot: string, options: PushOptions) =>
|
|
|
164
159
|
const emitBranchName =
|
|
165
160
|
options.emit || options.branch || branchInfo.emitBranch
|
|
166
161
|
|
|
167
|
-
// If skipFilter, we skipped emit() so we must create the emit branch manually
|
|
168
|
-
if (options.skipFilter) {
|
|
169
|
-
yield* git.createOrResetBranch(gitRoot, emitBranchName, sourceBranch)
|
|
170
|
-
// Switch back to source branch for consistency
|
|
171
|
-
yield* git.checkoutBranch(gitRoot, sourceBranch)
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
log(done(`Emitted ${highlight.branch(emitBranchName)}`))
|
|
175
|
-
|
|
176
162
|
// Step 2: Push to remote (git push)
|
|
177
163
|
const remote = yield* getRemoteName(gitRoot)
|
|
178
164
|
verboseLog(
|