Show commit metadata note after push - #20
Conversation
- Add a new `eslint.config.js` for TypeScript source files with SonarJS and a cognitive complexity limit. - Add `lint` and `lint:ci` scripts to run ESLint across the project. - Add `eslint`, `typescript-eslint`, and `eslint-plugin-sonarjs` as development dependencies and update the lockfile.
- Add a new GitHub Actions job in `pr-validate.yml` to run `pnpm run lint:ci` on pull requests. - Set up repository checkout, Node.js 24, pnpm installation, and dependency installation for the lint workflow. - Keep the new job scoped to read-only repository contents permissions.
- Split `ModelSelector` keyboard handling into focused lifecycle, navigation, edit, and cursor helpers while preserving existing input behavior. - Add the `Key` type import for Ink input handlers and keep character insertion logic in the main `useInput` callback. - Remove obsolete ESLint suppression comments from JSON and maybe utilities. - Simplify `DateOnly.compare` to use chained `Math.sign` comparisons.
- Introduce `renderPushNote` in `src/infra/ui/push-note.ts` to display commit, branch, remote, and range info after a push. - Extend `src/infra/git/repo.ts` with `getUpstream`, `getCommitMetadata`, `getRemoteUrl`, and `PushResult`/`PushRange`/`CommitMetadata` types. - Refactor git helpers to share an `execGitChecked` utility and parse push ranges from git output. - Wire the commit CLI to gather metadata concurrently after a successful push and render the summary note.
- Add `src/infra/github/pr.ts` with `getOpenPullRequest` using `gh` CLI to look up the current branch's PR, classifying results as `found`, `unauthenticated`, or `unavailable`. - Extract `execBin` into `src/infra/shell.ts` and replace the private `execGit` helper in `repo.ts` with it; switch `performCommit` to `Future.bracket` for tmp file cleanup. - Extend `PushMetadata` with a `pr` field and render a PR line (or `gh auth login` hint) in `renderPushNote`. - Wire PR lookup into the `Commit` push flow so the push note surfaces the open PR URL.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f179c85df1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 82171d22e4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- Add rule requiring each bullet to end with a period across conventional and imperative prompts. - Remove `<classification>` tags from examples so the model no longer echoes size labels. - Update conventional prompt to use lowercase after the type prefix and include a multi-file example. - Inject `<git_diff>` into the custom template prompt so user templates receive diff context. - Extend refine prompt to preserve the original convention and output only the revised message.
- Add `getTrackingRemoteUrl` to resolve the remote URL from the current branch's upstream, falling back to `origin`. - Use the tracking remote URL when detecting GitHub PRs so forks and non-origin remotes are handled correctly. - Parse the `owner/repo` slug from the remote URL and pass it to `gh pr view` via `-R` for explicit repo targeting. - Use the tracking remote URL in commit push notes to reflect the actual push destination.
Motivation
In my workflow, it is quite common to address changes requested by a reviewer, and the need arose to have the commit metadata — especially the commit hash — to hand to the reviewer so they can verify my changes. This adjustment improves that feedback loop and surfaces more information about our commits after every push. Enjoy!
What's New
Post-Push Metadata Note
src/infra/ui/push-note.tsrenders a@clack/promptsnote with commit, author, date, branch, remote, range, and open PR after each pushrenderPushNoteconsumes aPushMetadatarecord combiningCommitMetadata,localBranch,upstream,remoteUrl,range, andprrenderPrLinepattern-matchesPrLookup(found/unauthenticated/unavailable) withabsurdfor exhaustiveness, surfacing agh auth logintip when the user is signed outsrc/cli/commit.tschainsperformPushwithFuture.concurrentlyto gather commit, branch, upstream, remote URL, and PR lookup in parallel before renderingformatDatenormalizes ISO timestamps toYYYY-MM-DD HH:MMfor readabilityGitHub PR Lookup
src/infra/github/pr.tswithgetOpenPullRequestinvokinggh pr view --json url,numberfor the current branchPrLookupdiscriminated union classifies outcomes asfound,unauthenticated, orunavailableGITHUB_HOST_REguards the call so non-GitHub remotes short-circuit tounavailablewithout spawningghGH_UNAUTH_REparses stderr to detect auth failures vs generic unavailabilitychainRejswallows unexpected errors intounavailableso the push note never fails because of PR lookupGit Repo Module Enhancements
getUpstream,getRemoteUrl, andgetCommitMetadatahelpers insrc/infra/git/repo.tsCommitMetadata,PushResult, andPushRangetypes for downstream consumersperformPushnow returns a structuredPushResultwith a parsedrange(before..after) viaparsePushRangeexecGithelper with the sharedexecBinfromsrc/infra/shell.tsperformCommitadoptsFuture.bracketto guarantee tmp file cleanup even on failureexecGitCheckedwrapper centralizes exit-code handling and error messaging across git invocationsShared Shell Primitive
src/infra/shell.tsexportsexecBin(bin, args)returningFuture<Error, ExecResult>Future.createwith a cancellation hook thatproc.kill()s on abortspawnerrors intoErrorinstances for downstream.chain/.chainRejcompositionLinting & CI Quality Gate
eslint.config.js) withtypescript-eslintparser andeslint-plugin-sonarjssonarjs/cognitive-complexityat threshold10to keep functions focusedlintandlint:ciscripts topackage.jsonCognitive complexityjob in.github/workflows/pr-validate.ymlgating PRs onpnpm run lint:ciModel Selector Refactor
useInputcallback intohandleLifecycle,handleNavigation,handleEdit, andhandleCursorbooleanto short-circuit dispatch inuseInputKeytype frominkfor handler signatureshandleEditfor cohesion with other edit operationsCleanup
eslint-disablecomments fromsrc/libs/json/encoder.ts,src/libs/json/schema.ts, andsrc/libs/maybe.tsDateOnly.compareusingMath.sign(...)chained with||packageManagerfield frompackage.jsonPost-Push Metadata Flow
graph TD A[CLI: Commit.push] --> B[loading spinner] B --> C[repo.performPush] C --> D{exit code 0?} D -- no --> E[Future.reject: Push failed] D -- yes --> F[PushResult: output + parsePushRange] F --> G[Future.concurrently] G --> H[getCommitMetadata] G --> I[getCurrentBranch] G --> J[getUpstream] G --> K[getRemoteUrl] H --> L[Combine parts + range] I --> L J --> L K --> L L --> M[renderPushNote] M --> N[clack note: commit / author / date / branch / remote / range] style F fill:#dbeafe,stroke:#1d4ed8 style G fill:#dbeafe,stroke:#1d4ed8 style M fill:#dcfce7,stroke:#16a34a style N fill:#dcfce7,stroke:#16a34aTesting & Feedback
--set-upstreamis triggered viapublishrangeappears for fast-forward pushes and is omitted when the push output does not contain a hash range (e.g. initial publish)--force-with-leaseand ensure the note still rendersCognitive complexityCI job on a deliberately complex function to confirm it fails, then verify it passes onmainModelSelectorkeybindings: arrows,Enter,Esc, backspace,Option+Delete,Ctrl+W,Ctrl+U,Option+Left/RightIf you find any bugs or have recommendations for improvements, please open an issue and assign it to me.