Skip to content

feat: ship @gitpulse/cli + reusable Pages workflow#26

Merged
znat merged 8 commits intomainfrom
feat/gitpulse-cli
May 4, 2026
Merged

feat: ship @gitpulse/cli + reusable Pages workflow#26
znat merged 8 commits intomainfrom
feat/gitpulse-cli

Conversation

@znat
Copy link
Copy Markdown
Owner

@znat znat commented May 3, 2026

Summary

  • Pivots from the never-shipped `@gitpulse/action` (yarn workspace, internal-only) to a publishable `@gitpulse/cli` npm package — usable in GH Actions, Vercel/Netlify build hooks, or any `npx` context. Env-vars only, no flags.
  • Adds a reusable Pages workflow (`publish-pages.yaml`) that wraps `npx @gitpulse/cli@0 analyze` + `build` + `actions/deploy-pages`. Replaces the previous `publish.yaml` which only worked for self-deploy of this repo.
  • Wires npm publish into release-please via Trusted Publishing (OIDC) — no NPM_TOKEN secret, short-lived credential minted per release.

Why

The earlier plan (a JS GitHub Action with ncc-bundled `dist/`) hit ncc/tsconfig friction (`allowImportingTsExtensions` + emit incompatibility). A CLI on npm:

  • Plain `tsc` build → no bundler, uses TS 5.7+ `rewriteRelativeImportExtensions` to keep `.ts` source imports while emitting `.js`.
  • Single artifact serves three surfaces: this Pages workflow, PaaS build hooks (`gitpulse analyze && gitpulse build` in `package.json`), and ad-hoc `npx` use.
  • Site-source distribution lives inside `gitpulse build` (clones matching tag, runs Next export) instead of being awkward shell glue inside a workflow.

Distribution surface (final)

Surface Audience
`@gitpulse/cli` on npm Everyone — primitive
`znat/gitpulse/.github/workflows/publish-pages.yaml@v0` Pages users (one-line install)
`gitpulse analyze && gitpulse build` in `package.json` Vercel / Netlify / Cloudflare Pages
README recipe (later PR) S3 / custom

Key changes

  • `action/` → `cli/` (workspace renamed, package `@gitpulse/action` → `@gitpulse/cli`, dropped `private: true`, added `bin`/`main`/`exports`/`files`/repo metadata)
  • New `cli/src/cli.ts` — env-only dispatcher with shebang
  • New `cli/src/build.ts` — clones matching tag, copies data, runs `yarn workspace @gitpulse/site build`, copies output to `GITPULSE_OUT_DIR`
  • New `cli/tsconfig.build.json` — emit-mode using `rewriteRelativeImportExtensions`
  • `site/next.config.js` — `GITPULSE_BASE_PATH` env override (Vercel/Netlify can set `""` to disable Pages `//` prefix)
  • `self-deploy.yml` — rewritten inline using local CLI workspace (dogfoods bleeding-edge, no npm dependency)
  • `release-please.yml` — added `publish-cli` job using OIDC + npm 11
  • `release-please-config.json` + manifest — added `cli` package
  • `ci.yml` — added `yarn workspace @gitpulse/cli build` verification step

Pre-1.0 versioning note

Currently `0.1.0`. Bootstrap publish landed `@gitpulse/cli@0.0.1` to seed the package on npm and configure Trusted Publishing; first release-please-driven publish will ship `0.1.0` via OIDC. Consumers pin `@v0` / `@gitpulse/cli@0` until `1.0.0` cuts.

Test plan

  • CI passes on this PR (typecheck, vitest x2 workspaces, `yarn workspace @gitpulse/cli build`)
  • After merge: `self-deploy.yml` runs end-to-end against this repo using the local CLI; https://znat.github.io/gitpulse/ updates
  • After merge: release-please opens a release PR; merging it triggers `publish-cli` job → `@gitpulse/cli@0.1.0` published via OIDC
  • Smoke test from a throwaway repo with Pages enabled:
    ```yaml
    jobs:
    publish:
    uses: znat/gitpulse/.github/workflows/publish-pages.yaml@v0
    secrets: inherit
    ```

Manual setup steps (one-time, post-merge)

  1. On https://www.npmjs.com/package/@gitpulse/cli/access → "Trusted Publishers" → add: GitHub Actions, owner `znat`, repo `gitpulse`, workflow `release-please.yml`.
  2. (Optional) Deprecate the `0.0.1` bootstrap: `npm deprecate @gitpulse/cli@0.0.1 "bootstrap publish"`.

Out of scope (separate PRs)

  • README rewrite documenting new surfaces (CLI, Pages workflow, Vercel/Netlify recipe).
  • README MiniMax/Anthropic example fix.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Official CLI published and runnable via npx for repository analysis and static site builds.
    • Configurable site base-path/asset-prefix to control deployment paths and URLs.
  • Chores

    • CI/CD and Pages pipelines updated to run analysis and builds through the CLI; release process now supports CLI releases and npm publishing.
    • Workspace and release manifest updated to include the CLI package.
  • Documentation

    • README rewritten with quickstarts, platform integration examples, and publishing guidance.

Replaces the internal @gitpulse/action workspace with a publishable
@gitpulse/cli package exposing `analyze` and `build` subcommands via
env-only configuration. Drops the JS-action approach (ncc bundling
fragility) for a single npm artifact that works in GH Actions,
Vercel/Netlify build hooks, and local dev.

- Rename action/ → cli/ workspace (package @gitpulse/action → @gitpulse/cli)
- cli/src/cli.ts: subcommand dispatcher (analyze | build | --version | --help)
- cli/src/build.ts: clones matching gitpulse tag, runs Next static export
- cli/tsconfig.build.json: emit-mode tsc with rewriteRelativeImportExtensions
- .github/workflows/publish-pages.yaml: reusable workflow consuming
  npx @gitpulse/cli@0 (replaces broken-for-externals publish.yaml)
- self-deploy.yml: rewritten inline using local CLI workspace
- release-please.yml: publish-cli job via Trusted Publishing (OIDC, no token)
- release-please config: add cli package for linked versioning
- site/next.config.js: GITPULSE_BASE_PATH override for non-Pages deploys
- ci.yml: verify CLI tsc build on every PR

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces a new @gitpulse/cli workspace and CLI (commands: analyze, build), removes the @gitpulse/action package config, adds a clone-and-build orchestrator, adjusts site basePath/URL resolution, updates CI/CD workflows to build/publish the CLI and site artifacts, and updates docs and release manifest/configuration.

Changes

CLI Tooling & Release Pipeline

Layer / File(s) Summary
Workspace & Manifest
package.json, .release-please-manifest.json, release-please-config.json
Root workspace now includes cli (replacing action); release-please manifest/config add a distinct cli package entry.
Package Metadata
cli/package.json, action/package.json
Added cli/package.json (ESM, bin gitpulse, Node>=22); removed action/package.json.
TypeScript Build Config
cli/tsconfig.build.json
New build tsconfig; emits JS to dist, source maps enabled, relative import extension rewrite.
Analyzer Core
cli/src/index.ts, cli/src/config.ts
main() replaced by exported runAnalyzer(): Promise<AnalyzerResult> returning {dataDir, storiesCount, releasesCount, newStoriesCount}; loadConfig defaults dataDir to ${repoDir}/.gitpulse/data and changes siteUrl fallback semantics.
Build Orchestrator
cli/src/build.ts
New runBuild() validates dataDir, asserts safe siteRepo/siteRef, clones repo@ref, copies analyzed data to site/public/data, sanitizes env, runs yarn install and yarn workspace @gitpulse/site build, and writes outDir.
CLI Entrypoint
cli/src/cli.ts
New CLI dispatcher supporting analyze, build, --version, --help; global error handling and exit codes.
Site Runtime Config
site/next.config.js, site/src/lib/seo.ts
basePath/assetPrefix resolution now honors GITPULSE_BASE_PATH (auto/none/literal); getBaseUrl() updated to consider GITPULSE_BASE_PATH, trim trailing /, and return '' when appropriate.
Workflows - CI / Pages / Release / Self-deploy
.github/workflows/ci.yml, .github/workflows/publish-pages.yaml, .github/workflows/release-please.yml, .github/workflows/self-deploy.yml
CI test adds yarn workspace @gitpulse/cli build. publish-pages renamed and runs npx -y @gitpulse/cli@0 analyze then ... build (artifact ./.gitpulse/out). release-please exports CLI-scoped outputs and adds publish-cli job (build & npm publish via OIDC); move-major-tag gated on CLI release. self-deploy replaced with explicit build + deploy jobs using local CLI workspace, with permissions and concurrency set.
Docs / Quickstart
README.md
README rewritten to document CLI + static deploy architecture, updated quickstart/platform examples, environment-variable configuration, local dev instructions, and trusted publishing guidance.

Sequence Diagram(s)

sequenceDiagram
    participant GHWF as GitHub Workflow
    participant CLI as `@gitpulse/cli`
    participant Repo as Site Repo (clone/build)
    participant Pages as GitHub Pages
    participant NPM as npm Registry

    GHWF->>CLI: npx `@gitpulse/cli` analyze (env: AI_*, GITPULSE_*, OPENAI_API_KEY)
    CLI-->>GHWF: AnalyzerResult (dataDir, counts)
    GHWF->>CLI: npx `@gitpulse/cli` build (GITPULSE_BASE_PATH, GITPULSE_SITE_URL)
    CLI->>Repo: git clone repo@ref
    CLI->>Repo: copy analyzed data -> site/public/data
    CLI->>Repo: yarn install && yarn workspace `@gitpulse/site` build
    Repo-->>GHWF: built site output (./.gitpulse/out)
    GHWF->>Pages: deploy artifact
    alt CLI release created
        GHWF->>NPM: build CLI, npm publish (OIDC/provenance)
        NPM-->>GHWF: publish result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 Hopping through the CI and tree,
I learned to build and analyze with glee,
A CLI sprouts where actions stood,
It clones, it builds, it publishes good,
Hop on—site and package flourish free! 🌱

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: ship @gitpulse/cli + reusable Pages workflow' clearly and specifically summarizes the main changes: introducing the @gitpulse/cli package and a reusable GitHub Pages workflow.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/gitpulse-cli

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 3, 2026

Greptile Summary

This PR pivots from an internal @gitpulse/action workspace to a publishable @gitpulse/cli npm package and adds a reusable publish-pages.yaml GitHub Actions workflow. The new gitpulse build command clones the matching site tag, injects analyzer data, and runs a static export — replacing the previous awkward shell glue. Previously-flagged issues (secret forwarding in build.ts, dataDir default mismatch, publish-cli using root package outputs) are all resolved in this revision.

Confidence Score: 4/5

Safe to merge; previously flagged P1 issues are resolved and only P2 style concerns remain.

No P0 or P1 issues found in the current diff. All previously-flagged blocking issues (secret env forwarding, dataDir mismatch, wrong release-please output keys) are addressed. Two P2 findings remain: SHA pinning inconsistency in publish-pages.yaml and the implicit yarn dependency in gitpulse build that could trip up npm/pnpm consumers.

cli/src/build.ts (yarn dependency for PaaS consumers), .github/workflows/publish-pages.yaml (SHA pinning of upload/deploy actions)

Important Files Changed

Filename Overview
cli/src/build.ts New file implementing gitpulse build: clones the matching gitpulse site tag, copies analyzer output, and runs the static export. Previously-flagged secret-forwarding issue is now properly addressed via sanitizeEnvForClonedBuild. Minor: yarn is required in PATH, which may not hold for npm/pnpm consumers.
cli/src/cli.ts New entry-point dispatcher for gitpulse analyze / gitpulse build commands; uses top-level await (valid with NodeNext ESM module). Clean and straightforward.
cli/src/config.ts Default dataDir updated from site/public/data to .gitpulse/data, aligning with build.ts default so zero-config analyze → build works without GITPULSE_DATA_DIR.
.github/workflows/publish-pages.yaml New reusable workflow: runs npx @gitpulse/cli@0 analyze + build then deploys to GitHub Pages. Required permissions are documented in comments. upload-pages-artifact and deploy-pages lack SHA pinning unlike other actions in the file.
.github/workflows/release-please.yml Added publish-cli job using OIDC Trusted Publishing; correctly uses cli--release_created and cli--tag_name namespaced outputs. linked-versions plugin keeps root and cli versions in lockstep, ensuring siteRef = v${cliVersion} resolves to a real tag.
.github/workflows/self-deploy.yml Rewritten to use local workspace CLI for analysis and direct site build. Correctly overrides GITPULSE_DATA_DIR to site/public/data for in-place builds.
site/next.config.js Added GITPULSE_BASE_PATH override logic with three sentinels: auto/empty → /<repo>, none → empty string, literal otherwise. Also exposes NEXT_PUBLIC_BASE_PATH for client-side use.
site/src/lib/seo.ts New file centralizing URL helpers and metadata builders. getBaseUrl() mirrors next.config.js base-path resolution and correctly warns when a non-auto base-path is used without an explicit GITPULSE_SITE_URL.
release-please-config.json Added cli package; uses linked-versions plugin to keep root and cli at the same version, include-component-in-tag: false so tags stay as v0.1.0, matching build.ts's default siteRef.

Sequence Diagram

sequenceDiagram
    participant Consumer as Consumer Workflow
    participant PY as publish-pages.yaml
    participant CLI as @gitpulse/cli (npx)
    participant GH as GitHub API
    participant Site as znat/gitpulse (cloned)
    participant Pages as GitHub Pages

    Consumer->>PY: workflow_call (secrets: inherit)
    PY->>CLI: npx @gitpulse/cli@0 analyze
    CLI->>GH: fetch commits, PRs, releases
    GH-->>CLI: data
    CLI->>CLI: LLM summarization
    CLI-->>PY: writes .gitpulse/data/

    PY->>CLI: npx @gitpulse/cli@0 build
    CLI->>Site: git clone v{cliVersion} (sanitized env)
    CLI->>Site: cp .gitpulse/data to site/public/data
    CLI->>Site: yarn install + next build (export)
    Site-->>CLI: site/out/
    CLI-->>PY: writes .gitpulse/out/

    PY->>Pages: upload-pages-artifact + deploy-pages
    Pages-->>Consumer: deployed URL
Loading

Fix All in Claude Code

Reviews (8): Last reviewed commit: "fix: document required permissions on th..." | Re-trigger Greptile

Comment thread .github/workflows/release-please.yml Outdated
Comment thread cli/src/build.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish-pages.yaml:
- Around line 18-50: Add two new reusable workflow inputs named "base-path" and
"site-url" so callers can override GITPULSE_BASE_PATH and GITPULSE_SITE_URL;
update the inputs block (near existing ai-model, ai-protocol, ai-base-url, etc.)
to declare these as string inputs with empty defaults, and then ensure the
job/step that sets environment variables passes them through (use the input
identifiers base-path and site-url where env GITPULSE_BASE_PATH and
GITPULSE_SITE_URL are populated). This mirrors the existing pattern for
ai-base-url and keeps behavior consistent when callers supply custom values.

In @.github/workflows/release-please.yml:
- Line 92: Replace the non-deterministic "run: npm install -g npm@latest" step
with a pinned npm version to ensure reproducible releases (e.g., change to
"npm@11.9.0"); update the workflow step that runs the install command so it
references a specific version (or an env variable like NPM_VERSION set to a
known-good release) instead of "npm@latest" so CI always uses the pinned npm CLI
version.
- Around line 76-77: The publish-cli job is gated by
needs.release-please.outputs.release_created which is true for any release;
update the release-please job to expose the paths_released output (add
outputs.paths_released to the release-please job) and change the publish
condition to inspect needs.release-please.outputs.paths_released for the CLI
package path (use needs.release-please.outputs.paths_released and check it
contains the CLI release path/component, e.g., the CLI package directory or
identifier) so the job only runs when the CLI component was actually released.

In `@release-please-config.json`:
- Around line 13-15: The release tags are colliding because the package scope
isn't included in tag names; update the release-please configuration to enable
component-scoped tags by adding "include-component-in-tag": true to the package
config for "cli" (and any other package entries like the root component) so
release-please will produce component-specific tags instead of shared tags
(e.g., include "include-component-in-tag": true alongside the "package-name":
"@gitpulse/cli" entry).

In `@site/next.config.js`:
- Around line 3-6: The canonical URL builder in the SEO helper must honor the
same basePath override used in next.config.js; update the code that constructs
the canonical/site URL (e.g., the function that builds the canonical URL, such
as getCanonicalUrl or getSiteMeta) to compute basePath the same way: derive
fallbackBasePath from GITHUB_REPOSITORY (repo ? `/${repo}` : ''), then set
basePath = process.env.GITPULSE_BASE_PATH ?? fallbackBasePath and include
basePath when forming the canonical URL (or prepend basePath to the path and
ensure trailing slash rules match assetPrefix); alternatively, if you prefer to
prevent mismatches, require that GITPULSE_SITE_URL is set whenever
GITPULSE_BASE_PATH is explicitly provided and throw or log a clear error in that
helper when basePath is overridden without a site URL.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 94531c9d-a6c9-4550-98cd-6a3969de13d6

📥 Commits

Reviewing files that changed from the base of the PR and between 0a31f0f and 296312b.

📒 Files selected for processing (38)
  • .github/workflows/ci.yml
  • .github/workflows/publish-pages.yaml
  • .github/workflows/release-please.yml
  • .github/workflows/self-deploy.yml
  • .release-please-manifest.json
  • action/package.json
  • cli/package.json
  • cli/src/build.ts
  • cli/src/categories.ts
  • cli/src/category-helpers.ts
  • cli/src/cli.ts
  • cli/src/commit-context.ts
  • cli/src/config.ts
  • cli/src/git.ts
  • cli/src/github.ts
  • cli/src/index.ts
  • cli/src/llm.ts
  • cli/src/pmap.test.ts
  • cli/src/pmap.ts
  • cli/src/release-builder.test.ts
  • cli/src/release-builder.ts
  • cli/src/release-llm.ts
  • cli/src/release-render.ts
  • cli/src/render.ts
  • cli/src/schemas.test.ts
  • cli/src/schemas.ts
  • cli/src/site-fetcher.ts
  • cli/src/size.ts
  • cli/src/slugify.ts
  • cli/src/state.ts
  • cli/src/strip-schema.test.ts
  • cli/src/strip-schema.ts
  • cli/src/types.ts
  • cli/tsconfig.build.json
  • cli/tsconfig.json
  • package.json
  • release-please-config.json
  • site/next.config.js
💤 Files with no reviewable changes (1)
  • action/package.json

Comment thread .github/workflows/publish-pages.yaml
Comment thread .github/workflows/release-please.yml Outdated
Comment thread .github/workflows/release-please.yml Outdated
Comment thread release-please-config.json
Comment thread site/next.config.js
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

⛔ CodeRabbit does not have permission to push changes to this repository. Please ensure CodeRabbit has Contents: Read and write permission.

… hygiene, basePath sentinel)

Addresses review comments from greptile + coderabbitai on PR #26.

P1 — Default dataDir mismatch broke zero-config consumer flow
  cli/src/config.ts default now matches build.ts (${repoDir}/.gitpulse/data).
  self-deploy.yml already overrides explicitly to site/public/data.

P1 — release-please publish-cli used root-package outputs
  Switched publish-cli + move-major-tag to read cli-namespaced outputs
  (`cli--release_created`, `cli--tag_name`, `cli--major`) so CLI-only
  releases actually publish, and the v0/v1 floating tag tracks the cli.

P2 — Caller env (incl. secrets) leaked into cloned-repo build
  cli/src/build.ts now sanitizes process.env before invoking yarn install
  + next build inside the temp clone. Strips OPENAI_API_KEY, GITHUB_TOKEN,
  AWS keys, NPM_TOKEN, plus a *_TOKEN/_SECRET/_PASSWORD/_API_KEY heuristic.

publish-pages.yaml — added base-path + site-url inputs
  base-path defaults to "auto" (sentinel = derive /<repo> from
  GITHUB_REPOSITORY). Set "none" for root deployments (user/org Pages,
  custom domain) or a literal prefix like "/blog". Resolved consistently
  in next.config.js.

site/src/lib/seo.ts — aligned canonical URL with basePath override
  When GITPULSE_BASE_PATH is overridden away from the GH-Pages-default,
  the auto-derived owner.github.io/repo URL is wrong. Suppresses the
  fallback in that case (returns empty so canonicals are path-only) and
  logs a warning, forcing the consumer to set GITPULSE_SITE_URL.

cli/src/config.ts — siteUrl uses `||` instead of `??`
  Empty-string env (common when CI workflows always set the var) now
  falls back to autoSiteUrl rather than producing an empty siteUrl.

release-please.yml — pinned npm to 11.9.0
  Reproducibility — bump deliberately when adopting new features.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/release-please.yml (1)

64-64: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin actions/checkout and actions/setup-node to immutable SHAs in this release workflow.

Lines 64, 93, and 96 use mutable @v6 tags in the publish path. For release security, pin these to full commit SHAs.

Suggested hardening diff
-      - uses: actions/checkout@v6
+      - uses: actions/checkout@<full-commit-sha> # v6.x.y

-      - uses: actions/checkout@v6
+      - uses: actions/checkout@<full-commit-sha> # v6.x.y

-      - uses: actions/setup-node@v6
+      - uses: actions/setup-node@<full-commit-sha> # v6.x.y
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release-please.yml at line 64, The workflow uses mutable
tags for GitHub Actions (e.g., actions/checkout@v6 and actions/setup-node@v* in
the release workflow) which should be pinned to immutable commit SHAs; find the
usages of actions/checkout@v6 and actions/setup-node@... in the release-please
workflow and replace each mutable tag with the corresponding full commit SHA
from the action's repository (use the action repo’s tags page to copy the commit
SHA), ensuring all occurrences in the publish/release steps are updated
consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish-pages.yaml:
- Around line 101-103: The build-step comment incorrectly states that an empty
string ("") maps to root deployments; update the comment near the
GITPULSE_BASE_PATH environment setting (GITPULSE_BASE_PATH: ${{ inputs.base-path
}}) to say that the resolver uses "none" to denote root deployments and that an
empty value means auto/fallback instead of root, so callers are not misled about
base-path semantics.

---

Outside diff comments:
In @.github/workflows/release-please.yml:
- Line 64: The workflow uses mutable tags for GitHub Actions (e.g.,
actions/checkout@v6 and actions/setup-node@v* in the release workflow) which
should be pinned to immutable commit SHAs; find the usages of
actions/checkout@v6 and actions/setup-node@... in the release-please workflow
and replace each mutable tag with the corresponding full commit SHA from the
action's repository (use the action repo’s tags page to copy the commit SHA),
ensuring all occurrences in the publish/release steps are updated consistently.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4795f515-0f9e-40b2-9503-a68a361bcdff

📥 Commits

Reviewing files that changed from the base of the PR and between 296312b and d2e7c9c.

📒 Files selected for processing (6)
  • .github/workflows/publish-pages.yaml
  • .github/workflows/release-please.yml
  • cli/src/build.ts
  • cli/src/config.ts
  • site/next.config.js
  • site/src/lib/seo.ts

Comment thread .github/workflows/publish-pages.yaml Outdated
… fix stale comment

Second round of PR #26 review fixes from coderabbitai.

release-please.yml — pin actions/checkout + actions/setup-node to SHAs
  Release path was using mutable @v6 tags. Now pinned alongside the existing
  release-please-action SHA pin. Dependabot rotates these via .github/dependabot.yml.
    actions/checkout    → de0fac2 # v6.0.2
    actions/setup-node  → 48b55a0 # v6.4.0

release-please-config.json — add linked-versions plugin
  With "include-component-in-tag": false and two packages (gitpulse + @gitpulse/cli),
  release-please could in principle desync versions and produce ambiguous tags.
  linked-versions forces both packages to bump together to the same version,
  eliminating the collision concern without uglifying tag names (which would
  break consumers who pin uses: znat/gitpulse/.github/workflows/publish-pages.yaml@v0).

publish-pages.yaml — fix outdated base-path comment
  Comment still referenced "" for root deployments; the resolver now uses
  the "none" sentinel (empty falls back to auto/derive). Updated to document
  all three sentinels next to the env wiring.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/publish-pages.yaml:
- Around line 59-63: The reusable workflow currently declares the OPENAI_API_KEY
secret as optional (required: false) which allows callers to omit it and leads
to runtime failures when tools like gitpulse analyze expect it; update the
OPENAI_API_KEY secret definition in the workflow to be required (set required:
true) so the workflow contract enforces presence, and ensure any callers provide
that secret when invoking the reusable workflow (search for the OPENAI_API_KEY
secret block in the publish-pages.yaml workflow to make this change).
- Around line 55-58: Add a runtime validation step to fail fast when the
workflow input site-url is empty but base-path is not "auto"; specifically,
after inputs are read (referencing the workflow inputs "site-url" and
"base-path" in publish-pages.yaml) add a step that checks if base-path != "auto"
and site-url == "" and then exits non‑zero with a clear error message. This
ensures the action fails early instead of silently falling back to the Pages URL
and prevents incorrect canonical/restore links.
- Around line 75-82: Replace the mutable action tags in the reusable workflow
with SHA-pinned refs: update the uses entries that currently read
"actions/checkout@v6" and "actions/setup-node@v6" to the corresponding commit
SHAs (matching how release-please.yml pins these actions). Locate the uses lines
for actions/checkout and actions/setup-node in publish-pages.yaml and replace
the `@v6` tags with the exact commit SHAs for those actions, keeping the existing
with: blocks (fetch-depth and node-version) unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bded6e6e-190c-48ef-8355-d60fbef4ee03

📥 Commits

Reviewing files that changed from the base of the PR and between d2e7c9c and 24fa523.

📒 Files selected for processing (3)
  • .github/workflows/publish-pages.yaml
  • .github/workflows/release-please.yml
  • release-please-config.json

Comment thread .github/workflows/publish-pages.yaml
Comment thread .github/workflows/publish-pages.yaml
Comment thread .github/workflows/publish-pages.yaml Outdated
…ecture

The previous README documented the old @gitpulse/action workspace pattern that
only worked for self-deploy. Replaces it with concrete deploy recipes for the
new distribution surfaces:

- GitHub Pages — uses: znat/gitpulse/.github/workflows/publish-pages.yaml@v0
- Vercel — gitpulse analyze && gitpulse build && next build in package.json
- Netlify — equivalent in netlify.toml
- Cloudflare Pages — build command in dashboard
- Generic (S3, GitLab CI, custom) — CLI invocation via npx

Also documents:
- Env-only configuration (no flags) with full var table
- LLM provider examples (OpenAI / MiniMax / Groq / OpenRouter / Anthropic)
- gitpulse build internals (clone matching tag, sanitize env, next export)
- Local dev commands (yarn workspace @gitpulse/cli analyze)
- Updated release flow: linked-versions, OIDC publish, Trusted Publishing setup

Pre-1.0 versioning is called out at the top — consumers pin @0 / @v0 until
the API stabilises.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Around line 164-205: The fenced code blocks under the provider examples
("OpenAI", "MiniMax", "Groq", "OpenRouter", "Anthropic Claude") lack surrounding
blank lines and trigger markdownlint MD031; fix by adding one empty line
immediately before and one empty line immediately after each triple-backtick
block so each provider header and the following paragraph are separated from the
```yaml``` block and the README passes CI.
- Around line 212-220: The fenced CLI help block containing "gitpulse <command>"
is missing a language tag; update the Markdown fence to specify a language such
as `text` or `bash` (e.g., change ``` to ```text) so the block renders
consistently and satisfies lint rule MD040; locate the fenced block that lists
the analyze/build/--version/--help commands in README.md and add the language
immediately after the opening triple backticks.
- Line 28: The README's major-tag guidance incorrectly suggests keeping the
reusable workflow pinned to `@v0` after graduating to a stable major; update the
sentence that currently reads the workflow as
`znat/gitpulse/.github/workflows/publish-pages.yaml@v0` and the trailing “When
the API stabilises, both move to `@1` / `@v0`” to instruct moving both to the
same stable major tags (e.g., `@1` for npm and `@v1` for the workflow) so the
sentence shows `@1 / `@v1`` instead of `@1 / `@v0``.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0ec17de8-4bae-4d5f-b4e1-59a9158a3d4c

📥 Commits

Reviewing files that changed from the base of the PR and between 24fa523 and 5157eb0.

📒 Files selected for processing (1)
  • README.md

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread .github/workflows/publish-pages.yaml
Trimming README provider examples to the most representative set
(OpenAI, MiniMax, OpenRouter, Anthropic). Groq still works via the
generic OpenAI-compatible pattern — anyone wanting it can derive
from OpenRouter or MiniMax examples.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Around line 70-78: The Vercel/Netlify/Cloudflare environment variable examples
are missing the required GITHUB_REPOSITORY var referenced elsewhere (e.g., where
GITHUB_REPOSITORY is declared required), causing non-GitHub Actions deploys to
fail; update the examples to include GITHUB_REPOSITORY with guidance on its
value (owner/repo) or document a fallback behavior and mark it optional where
applicable (references: the README env table entries and the GITHUB_REPOSITORY
requirement declaration).
- Line 213: Update the README command description so it matches the actual
implementation in cli/src/build.ts: change the reference from "yarn install /
next build" to the actual invoked command "yarn install / yarn run next export"
(or simply "yarn run next export"), and ensure the sentence still states that
secrets (OPENAI_API_KEY, GITHUB_TOKEN, etc.) are stripped from the env passed to
the cloned tree before running the export; reference the gitpulse build command
and build.ts to locate the logic to mirror.
- Around line 48-49: The README currently documents using "secrets: inherit"
alongside the reusable workflow reference "uses:
znat/gitpulse/.github/workflows/publish-pages.yaml@v0"; change the example to
remove "secrets: inherit" and instead show explicit secret mappings for only the
required secrets (e.g., map GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} or any
specific DEPLOY_KEY) so callers explicitly pass least-privilege secrets when
invoking the reusable workflow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 047fd812-479b-4040-bf8c-227fcdeb19e1

📥 Commits

Reviewing files that changed from the base of the PR and between 5157eb0 and 814b007.

📒 Files selected for processing (1)
  • README.md

Comment thread README.md
Comment thread README.md
Comment thread README.md
3. **Summarize** each commit with one LLM call: headline, standfirst, category, size assessment.
4. **Restore** prior content by fetching `data/state.json`, `data/manifest.json`, and `data/stories/<id>.json` from the live deployed site — no database, no separate branch, no artifact chain.
5. **Build** the Next.js site (`output: 'export'`) and **deploy** to GitHub Pages.
`gitpulse build` clones `znat/gitpulse@v<cli-version>` to a temp dir, copies your `GITPULSE_DATA_DIR` into the site's `public/data/`, runs the Next.js export, and copies the result to `GITPULSE_OUT_DIR`. It strips secrets (`OPENAI_API_KEY`, `GITHUB_TOKEN`, etc.) from the env it passes to the cloned tree's `yarn install` / `next build`.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 4, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Command description drifts from implementation (next build vs next export).

Line 213 says env is passed to yarn install / next build, but the build flow shown in cli/src/build.ts invokes yarn run next export. Update wording so docs match behavior.

Suggested doc change
-It strips secrets (`OPENAI_API_KEY`, `GITHUB_TOKEN`, etc.) from the env it passes to the cloned tree's `yarn install` / `next build`.
+It strips secrets (`OPENAI_API_KEY`, `GITHUB_TOKEN`, etc.) from the env it passes to the cloned tree's `yarn install` / `next export`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
`gitpulse build` clones `znat/gitpulse@v<cli-version>` to a temp dir, copies your `GITPULSE_DATA_DIR` into the site's `public/data/`, runs the Next.js export, and copies the result to `GITPULSE_OUT_DIR`. It strips secrets (`OPENAI_API_KEY`, `GITHUB_TOKEN`, etc.) from the env it passes to the cloned tree's `yarn install` / `next build`.
`gitpulse build` clones `znat/gitpulse@v<cli-version>` to a temp dir, copies your `GITPULSE_DATA_DIR` into the site's `public/data/`, runs the Next.js export, and copies the result to `GITPULSE_OUT_DIR`. It strips secrets (`OPENAI_API_KEY`, `GITHUB_TOKEN`, etc.) from the env it passes to the cloned tree's `yarn install` / `next export`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` at line 213, Update the README command description so it matches
the actual implementation in cli/src/build.ts: change the reference from "yarn
install / next build" to the actual invoked command "yarn install / yarn run
next export" (or simply "yarn run next export"), and ensure the sentence still
states that secrets (OPENAI_API_KEY, GITHUB_TOKEN, etc.) are stripped from the
env passed to the cloned tree before running the export; reference the gitpulse
build command and build.ts to locate the logic to mirror.

Copy link
Copy Markdown
Owner Author

@znat znat May 4, 2026

Choose a reason for hiding this comment

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

Reviewer claim is incorrect. The site is on Next.js 16.1.6 with output: 'export' in next.config.js — the standalone next export subcommand was removed in Next 14 (the export pathway has been driven by config + next build for several majors now). Site package.json literally has "build": "next build --webpack", and build.ts invokes that via yarn workspace @gitpulse/site build. next build in the README is correct as written.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@znat, you're absolutely right — I apologize for the incorrect suggestion. The official Next.js documentation confirms this: "The next export command has been removed in favor of output: 'export' config." This removal happened in Next.js 14, with next export softly deprecated in Next.js 13.3 and removed entirely in Next.js 14. Since the site uses output: 'export' in next.config.js and the build script invokes next build, the README wording is correct as-is. My suggestion to change it to next export would have documented a command that no longer exists.


✏️ Learnings added
Learnt from: znat
Repo: znat/gitpulse PR: 26
File: README.md:282-282
Timestamp: 2026-05-04T07:29:09.491Z
Learning: In the gitpulse repository (`znat/gitpulse`), the site workspace (`site/`) uses modern Next.js (14+) with `output: 'export'` in `next.config.js`. The `next export` standalone subcommand was removed in Next.js 14; static exports are now produced by running `next build` (which respects the `output: 'export'` config). The site's build script is `"build": "next build --webpack"`, and `cli/src/build.ts` invokes it via `yarn workspace gitpulse/site build`. Do not suggest replacing `next build` with `next export` in this codebase.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

znat and others added 3 commits May 4, 2026 08:52
…; drop releasing

Three README adjustments based on review feedback:

- Wrapped each Quickstart deploy option in <details> (Pages open by default,
  others collapsed) so the page scans cleanly.
- Restructured LLM providers section: header now shows env-var wiring for
  each deploy target (Pages workflow `with:`, Vercel/Netlify dashboard,
  generic GH Actions `env:`, local `.env`), and each provider just lists
  the values to fill in. No more ambiguity about "which job do these go in".
- Dropped the Releasing section — that's maintainer-only material; lives in
  CONTRIBUTING/internal docs rather than user-facing README.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- publish-pages.yaml: mark OPENAI_API_KEY required: true (was false; the
  analyzer can't run without it, so workflow-contract failure beats runtime).
- publish-pages.yaml: add fail-fast validation step that errors when
  base-path is overridden away from 'auto' but site-url is empty —
  otherwise canonical URLs silently fall back to the wrong host.
- publish-pages.yaml: pin actions/checkout + actions/setup-node to SHAs
  (matches release-please.yml; reusable workflow runs in caller's context
  so SHA pinning matters even more here).
- README: add `text` language to the gitpulse --help fenced block (MD040).

Linked-versions plugin choice over `include-component-in-tag: true` is
intentional and stands; will note on the thread.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ges.yaml

Reusable workflows can't elevate beyond the caller's GITHUB_TOKEN scope.
Without explicit pages:write + id-token:write on the calling workflow,
the inner deploy job (actions/deploy-pages@v5) fails with permission-denied.

Updates the consumer-usage example in both:
- README.md (GitHub Pages Quickstart)
- publish-pages.yaml header comment

The next-export README comment from coderabbitai was incorrect (the site
uses modern Next.js with output: 'export' in config; the standalone
next export subcommand was removed in 13.5+). Replied on-thread; no
README change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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