Repository navigation
Add create-pr: a draft PR containing only one lesson's diff - #84
Merged
Merged
Conversation
Opens a draft PR on origin containing only one lesson's diff: pr-base/<slug> at the lesson's parent, pr/<slug> as one commit carrying the lesson's tree, refreshed in place on retakes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
commit: |
…d branch names - gh's --fill reads <remote>/<base>..<head> from local tracking refs, which a narrow fetch refspec or an unmatched remote leaves missing. Pass the same title/body explicitly instead. - rev-parse doesn't fail through Command.string, so a root lesson's missing parent was never detected; check for a sha. - Reject lesson ids that can't be branch names before pushing. - Drop the misleading commit count from the replace prompt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lable Private repos on GitHub Free don't support draft PRs, and `fork` creates private repos. Retry `gh pr create` without --draft, treat a failing `gh pr ready --undo` as non-fatal, and print a one-line note either way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
create-pr. A student runsnpm run create-pr <slug>and gets a draft PR on their own repo (origin) whose diff is exactly one lesson commit. Then they ask their agent to rewrite the PR body.Course
package.json:"create-pr": "ai-hero-cli create-pr --branch=live-run-through --upstream=<url>", the same flags asreset.Size: 3 commits (the feature, fixes from an independent review, then a fallback when drafts aren't available), about 410 lines of source and 750 lines of tests. Reading order:
src/create-pr.ts→src/github-service.ts(the newgh prmethods andparseGitHubRemoteUrl) →src/git-service/git-service-impl.ts(5 small primitives) →test/create-pr-e2e.test.ts.One departure from the spec: the spec asked for
gh pr create --fill. This passes--title/--bodyexplicitly instead, with the values--fillwould produce for a single-commit branch: the subject with the prefix stripped, and the body. The reason is that--fillrunsgit log <remote>/<base>..<head>on local remote-tracking refs. Those refs are missing when the clone has a narrow fetch refspec, or when gh can't matchoriginto--repo. Passing the values also guarantees that the create path and the retake path (gh pr edit) write the same title and body.Every
ghcall passes--repo <origin's owner/repo>. The reason: whilecreate-prruns, anupstreamremote exists, and gh ranksupstreamaboveoriginwhen it picks a base repo. Without--repo, the PR would target the course repo.Evidence
test/create-pr-e2e.test.tsruns the real GitService against real repos: anupstreambare repo withmainand the lesson stack, and anoriginbare repo reached through ahttps://github.com/student/course.gitURL rewritten locally withinsteadOf. Because of that rewrite, the GitHub-remote check runs for real.ghand prompts are faked.carries only the chosen lesson's diff for a lesson mid-stack: one commit on top of the parent, and only the lesson's files differmain's tipopens a draft PR whose base is main's tip…:pr-baseequalsmain, and theorigin/pr-base/<slug>tracking ref exists (--fillreads it)never gives the PR commit a subject the lesson lookup could match, plustoPrCommitMessageunit tests (repeated prefix, bareslug:)a retake after the stack is rewritten…: both refs are force-moved to the new shas, the student is asked beforepr/<slug>is replaced, and the open PR is edited and re-drafted rather than duplicatedoriginuntouchedfails before pushing anything when the lesson id can't be a branch nameforkcreates) rejects drafts, leaving pushed branches and no PRopens a ready-for-review PR when the repo's plan has no drafts(create retried without--draft);still refreshes an existing PR when it can't be turned back into a draftorigin, noorigin, onlive-run-through: all fail withoriginstill emptyai-hero create-pris not a command.After:
pnpm check,pnpm lintandpnpm testall pass, with 188 tests (160 before).Left out deliberately
git@github-work:me/repo) are read as an Enterprise host, socreate-prrefuses them with a clear error. This only matters for multi-account setups.ghis faked in tests. Thegh pr create,editandready --undoargument shapes, and howready --undobehaves on a PR that is already a draft, were checked against the gh v2.80 source.Handled: drafts on private repos
ai-hero forkcreates private repos, and GitHub only allows draft PRs on private repos on paid plans (Pro, Team, Enterprise). On GitHub Free:gh pr create --draftfails, the command retries without--draft.gh pr ready --undois not fatal.In both cases it prints a one-line note that the PR is ready-for-review because drafts aren't available on the repo's plan.
The fallback applies to any failure of
--draft, because gh's stderr goes straight to the terminal and isn't parsed. If the failure had another cause, the retry fails as well and its error is shown.Merge Danger
Door: two-way
It adds a new command and touches no existing behaviour. Once it is published and wired into course
package.jsons, thepr/<slug>andpr-base/<slug>branch names become a convention that students' repos hold.Blast Radius: additive
It only runs when invoked. It force-pushes two CLI-owned branch names on the student's
origin, and if the student has no git identity set, it writes a localuser.name/user.emailfrom their GitHub login, asforkdoes.🤖 Generated with Claude Code