Skip to content

Show commit metadata note after push - #20

Merged
rafaeelricco merged 14 commits into
mainfrom
metadata-after-commit
Apr 21, 2026
Merged

Show commit metadata note after push #20
rafaeelricco merged 14 commits into
mainfrom
metadata-after-commit

Conversation

@rafaeelricco

Copy link
Copy Markdown
Owner

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

  • New src/infra/ui/push-note.ts renders a @clack/prompts note with commit, author, date, branch, remote, range, and open PR after each push
  • renderPushNote consumes a PushMetadata record combining CommitMetadata, localBranch, upstream, remoteUrl, range, and pr
  • renderPrLine pattern-matches PrLookup (found / unauthenticated / unavailable) with absurd for exhaustiveness, surfacing a gh auth login tip when the user is signed out
  • Commit flow in src/cli/commit.ts chains performPush with Future.concurrently to gather commit, branch, upstream, remote URL, and PR lookup in parallel before rendering
  • formatDate normalizes ISO timestamps to YYYY-MM-DD HH:MM for readability

GitHub PR Lookup

  • New src/infra/github/pr.ts with getOpenPullRequest invoking gh pr view --json url,number for the current branch
  • PrLookup discriminated union classifies outcomes as found, unauthenticated, or unavailable
  • GITHUB_HOST_RE guards the call so non-GitHub remotes short-circuit to unavailable without spawning gh
  • GH_UNAUTH_RE parses stderr to detect auth failures vs generic unavailability
  • chainRej swallows unexpected errors into unavailable so the push note never fails because of PR lookup

Git Repo Module Enhancements

  • Add getUpstream, getRemoteUrl, and getCommitMetadata helpers in src/infra/git/repo.ts
  • Export CommitMetadata, PushResult, and PushRange types for downstream consumers
  • performPush now returns a structured PushResult with a parsed range (before..after) via parsePushRange
  • Replace the private execGit helper with the shared execBin from src/infra/shell.ts
  • performCommit adopts Future.bracket to guarantee tmp file cleanup even on failure
  • New execGitChecked wrapper centralizes exit-code handling and error messaging across git invocations

Shared Shell Primitive

  • New src/infra/shell.ts exports execBin(bin, args) returning Future<Error, ExecResult>
  • Built on Future.create with a cancellation hook that proc.kill()s on abort
  • Normalizes spawn errors into Error instances for downstream .chain / .chainRej composition

Linting & CI Quality Gate

  • Add ESLint 9 flat config (eslint.config.js) with typescript-eslint parser and eslint-plugin-sonarjs
  • Enforce sonarjs/cognitive-complexity at threshold 10 to keep functions focused
  • Add lint and lint:ci scripts to package.json
  • New Cognitive complexity job in .github/workflows/pr-validate.yml gating PRs on pnpm run lint:ci

Model Selector Refactor

  • Split monolithic useInput callback into handleLifecycle, handleNavigation, handleEdit, and handleCursor
  • Each handler returns boolean to short-circuit dispatch in useInput
  • Import Key type from ink for handler signatures
  • Regular backspace/delete moved into handleEdit for cohesion with other edit operations

Cleanup

  • Drop obsolete eslint-disable comments from src/libs/json/encoder.ts, src/libs/json/schema.ts, and src/libs/maybe.ts
  • Simplify DateOnly.compare using Math.sign(...) chained with ||
  • Remove packageManager field from package.json

Post-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:#16a34a
Loading

Testing & Feedback

  • Confirm the post-push note renders correctly both when the branch has an upstream and when --set-upstream is triggered via publish
  • Verify range appears for fast-forward pushes and is omitted when the push output does not contain a hash range (e.g. initial publish)
  • Run a push with --force-with-lease and ensure the note still renders
  • Trigger the new Cognitive complexity CI job on a deliberately complex function to confirm it fails, then verify it passes on main
  • Exercise the refactored ModelSelector keybindings: arrows, Enter, Esc, backspace, Option+Delete, Ctrl+W, Ctrl+U, Option+Left/Right

If you find any bugs or have recommendations for improvements, please open an issue and assign it to me.

- 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.
@rafaeelricco rafaeelricco self-assigned this Apr 21, 2026
@rafaeelricco

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/cli/commit.ts Outdated
Comment thread src/infra/github/pr.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/cli/commit.ts Outdated
- 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.
@rafaeelricco
rafaeelricco merged commit f9c6441 into main Apr 21, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant