Skip to content

ci(pullfrog): pin the action and make the reviewer review-only - #38

Merged
fabiodalez-dev merged 3 commits into
mainfrom
chore/pullfrog-review-only
Oct 1, 2026
Merged

fabiodalez-dev merged 3 commits into
mainfrom
chore/pullfrog-review-only

Conversation

@fabiodalez-dev

Copy link
Copy Markdown
Owner

The Pullfrog console generated this workflow when I enabled the repository. It works, but it leaves three things at defaults that are wrong for this project, so this tightens them before the reviewer starts running.

push: disabled. This is the one that matters. The input defaults to enabled, which lets the agent push branches and open pull requests of its own. Every commit and pull request in my repositories is authored by me, so the agent gets no write path at all: it reads the diff and comments. The input is declared in the action's own action.yml and is not mentioned in the getting-started guide, which is why the generated file leaves it permissive.

Pinned to a commit SHA instead of @v0. That tag moves — it has already advanced through ninety v0.1.x releases — and this is the only action here that runs an agent with access to the repository, so a mutable ref is the last place I want one. Pullfrog's own versioning page supports pinning and says nothing is lost: the action fetches its steps from npm either way, so the agent keeps tracking patch releases without this file changing. Bump the SHA to update.

shell: restricted, which scrubs *_TOKEN / *_KEY / *_SECRET / *_PASSWORD / *_CREDENTIAL out of the environment the agent's shell sees. It is already the default for a public repository; I set it explicitly so that making this repository private some day cannot widen it silently, since private repos default to enabled.

I left the provider env: block exactly as generated. I checked what an unset secret does: it resolves to an empty string, and the action's sanitizeSecret() leaves the variable untouched in that case rather than treating it as a key, so the block is inert until a key is actually added and it cannot shadow keys held in Pullfrog's own store or in the Router.

Nothing else changes. There are no run: steps, so there is no shell interpolation surface, and no workflow expression reads untrusted event data.

One caveat worth recording: the file carries Pullfrog's own DO NOT EDIT EXCEPT WHERE INDICATED header, so if the console regenerates it these three changes are lost. The durable place for the push tier is the console's own repository setting; this file is the belt to that braces.

Three changes to the workflow the Pullfrog console generated, each for a
reason that applies to this repository specifically.

`push: disabled`. The input defaults to `enabled`, which lets the agent push
branches and open pull requests of its own. Every commit and pull request here
is authored by its maintainer, so the agent gets no write path at all: it reads
the diff and comments. The input is declared in the action's own action.yml and
is not mentioned in the getting-started guide, so the generated file leaves it
at the permissive default.

Pinned to a commit SHA instead of `@v0`. That tag moves — it has already
advanced through ninety v0.1.x releases — and this is the one action here that
runs an agent with repository access, so a mutable ref is the last place to
accept one. Pullfrog's versioning page supports pinning and notes nothing is
lost: the action fetches its steps from npm either way, so the agent still
tracks patch releases without this file changing.

`shell: restricted`, which scrubs *_TOKEN / *_KEY / *_SECRET / *_PASSWORD /
*_CREDENTIAL from the environment the agent's shell sees. Already the default
for a public repository; stated explicitly so that making this repository
private some day cannot silently widen it, since private repos default to
`enabled`.

The provider `env:` block is left exactly as generated. Unset secrets resolve
to empty strings, and the action's sanitizeSecret() leaves the variable
untouched in that case rather than treating it as a key, so the block is inert
until a key is actually added and it cannot shadow keys held in Pullfrog's own
store or the Router.

Nothing else is touched: no `run:` steps, so no shell interpolation surface,
and no workflow expression reads untrusted event data.
@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 1aa5e74c-013f-459b-941c-644d56603948

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

  • Pinned the agent action to a commit SHA — pullfrog/pullfrog@v0 → @0d318bef…, the commit for tag v0.1.90 (confirmed against the upstream tag ref and the current releases/latest). Removes the mutable-tag supply-chain surface on the one action that runs with repository access.
  • Added push: disabled — the agent runs read-only and cannot create branches or pull requests.
  • Added shell: restricted explicitly — pins the secret-scrubbing behavior so a future switch to a private repo can't silently widen it to enabled.

Verification. Both push and shell are declared in the action's action.yml at that SHA, and each value used is a documented option. The comment's load-bearing claim — that a SHA pin still tracks ^0.1.x patches because the bootstrap resolves its steps from npm — holds: runCli.ts runs npx --yes pullfrog@^<package.json version> unless the ref is main, so npm resolution keeps advancing within the 0.1 line. No run: steps and no expression consumes untrusted event data, so no injection surface.


Important

Pullfrog covered this run's model usage. DeepSeek Flash is fast and cheap — expect lighter work than a frontier model. This model allowance is temporary and separate from your Pullfrog plan. Connect a model-provider subscription or API key →

Pullfrog  | View workflow run | Using DeepSeek Flash (model usage covered by Pullfrog) | 𝕏

actions/checkout defaults to persist-credentials: true, which writes the job's
GITHUB_TOKEN into .git/config. That leaves a working push credential inside the
very checkout the agent then operates on, so it contradicts the `push: disabled`
set alongside it: the input closes the action's own push path and the token
reopens it from underneath.

Caught by Pinakes' CI policy check — "pullfrog.yml has an actions/checkout step
that persists GitHub credentials" — which refuses any checkout that persists
credentials. It was right, and the same omission was in all of these
repositories, so the fix goes everywhere rather than only where a check happened
to be watching.

Nothing needs the credential: the agent reaches GitHub through the App's
installation token, not the local git remote, and these repositories are public,
so an unauthenticated fetch works.

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

This run re-reviewed the single commit added since the prior Pullfrog review (a5ca03d → 9f1f57f).

  • Stopped the checkout persisting a push credential — actions/checkout now takes persist-credentials: false, so the job's GITHUB_TOKEN is no longer written into .git/config. This closes the write path that push: disabled alone cannot: the input governs the action's own push feature, while the persisted token left an authenticated remote underneath it.
  • Documented the rationale inline — a nine-line comment explains the default, the contradiction with push: disabled, and why nothing here needs the credential.

Verification. The load-bearing claims in the comment check out. api.github.com/repos/fabiodalez-dev/Pinakes-Android reports private:false, so the unauthenticated fetch it relies on works. actions/checkout@v6 resolves to a real tag (pre-existing, unchanged by this PR). The Pullfrog agent reaches GitHub through the App installation token via the MCP server rather than the local checkout's credential, and play-bundle.yml:21 already runs a credential-free checkout in this repo — so disabling persistence cannot break PR checkout or fetch.


Important

Pullfrog covered this run's model usage. DeepSeek Flash is fast and cheap — expect lighter work than a frontier model. This model allowance is temporary and separate from your Pullfrog plan. Connect a model-provider subscription or API key →

Pullfrog  | View workflow run | Using DeepSeek Flash (model usage covered by Pullfrog) | 𝕏

The reviewer workflow was the only file in .github failing the Workflow, YAML
and shell security gate. Four separate problems, all real:

- zizmor (pedantic) wants every write permission documented, and it reads a
  trailing comment on the permission line, not a block above it. id-token:
  write now says on its own line what it is for: an OIDC identity for
  Pullfrog token service, which grants nothing on the repository.
- The job had no name, so it showed up anonymously in the checks list.
- The workflow had no concurrency group. It was left out on purpose, because
  every run is dispatched against the default branch and one shared group
  would make two reviews cancel each other. The group is keyed on the
  dispatched run name instead, so a fresh review of the same pull request
  supersedes a stale one while different pull requests never collide, and it
  falls back to the unique run id when no name is passed.
- Two lines carried trailing whitespace, inherited from the generated
  template, which yamllint rejects. The gate had never reached yamllint
  because zizmor failed first.

Also pins actions/checkout by commit SHA where it was still a floating v6 tag.

Verified locally with the same three tools the gate runs, over the whole
.github tree: zizmor --persona pedantic, actionlint and yamllint all exit 0.

@pullfrog pullfrog 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.

✅ No new issues found.

Reviewed changes

This run re-reviewed the single commit added since the prior Pullfrog review (9f1f57f → 4590501).

  • Pinned actions/checkout to a commit SHA — @v6 → @d23441a… # v6, closing the same mutable-ref surface that the earlier commit closed on the agent action.
  • Added a top-level concurrency group — keyed on the dispatcher-supplied run name, so a fresh review of the same pull request supersedes a stale one while reviews of different pull requests never collide; falls back to the unique run id when no name is passed.
  • Added a job name and explanatory comments on the top-level and job permissions blocks, and stripped trailing whitespace from the env: block.

Verification. api.github.com/repos/actions/checkout/git/ref/tags/v6 returns commit d23441a48e516b6c34aea4fa41551a30e30af803, so the pin and its # v6 comment match. inputs is an allowed context in a top-level concurrency for workflow_dispatch, and inputs.name || github.run_id falls back to the run id — unique per run — so cancel-in-progress cannot cancel unrelated runs. No run: steps and no expression consumes untrusted event data.


Important

Pullfrog covered this run's model usage. DeepSeek Flash is fast and cheap — expect lighter work than a frontier model. This model allowance is temporary and separate from your Pullfrog plan. Connect a model-provider subscription or API key →

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (model usage covered by Pullfrog) | 𝕏

@fabiodalez-dev
fabiodalez-dev merged commit 1865005 into main Oct 1, 2026
3 checks passed
@fabiodalez-dev
fabiodalez-dev deleted the chore/pullfrog-review-only branch October 1, 2026 15:50
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