Skip to content

chore(proto): auto-commit generated artifacts for internal PRs#3490

Open
lspassos1 wants to merge 5 commits into
koala73:mainfrom
lspassos1:chore/sebuf-codegen-ci
Open

chore(proto): auto-commit generated artifacts for internal PRs#3490
lspassos1 wants to merge 5 commits into
koala73:mainfrom
lspassos1:chore/sebuf-codegen-ci

Conversation

@lspassos1
Copy link
Copy Markdown
Collaborator

Summary

Moves generated proto/OpenAPI artifact churn out of normal internal PR review by teaching the proto freshness workflow to run make generate and push generated artifacts back to same-repository PR branches. Fork PRs keep a safe validation-only path with an explicit failure message because CI cannot safely push to contributor branches.

cc @koala73

Closes #3340

Type of change

  • CI / Build / Infrastructure
  • Documentation

Affected areas

  • Other: proto generation workflow and contributor docs

Root cause

The existing proto freshness check could detect stale generated files, but contributors still had to include generated artifacts manually in every PR. That creates noisy reviews and makes code changes harder to evaluate.

Changes

  • Run make generate in .github/workflows/proto-check.yml.
  • For internal PRs, auto-commit changes under src/generated/ and docs/api/ back to the PR branch.
  • For fork PRs, keep validation-only behavior with clear instructions to run make generate locally.
  • Quote the PR head ref through an environment variable before pushing.
  • Add job-level concurrency to cancel stale proto freshness runs for the same PR.
  • Document the generated artifact contract in CONTRIBUTING.md.

Validation

Risk

Moderate. The workflow gets write permissions for internal PR branches only. Forks remain validation-only, and the push target is quoted to avoid shell evaluation of branch names.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 28, 2026

@lspassos1 is attempting to deploy a commit to the World Monitor Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 28, 2026

Greptile Summary

This PR teaches the proto freshness workflow to auto-commit generated artifacts back to internal PR branches via git push, while keeping fork PRs on a validation-only path. The CONTRIBUTING.md update accurately documents the new contract.

  • P1 — untrusted fork code now executes on CI runners: Removing the job-level if guard means make install-buf install-plugins and make generate run against the fork's own Makefile for every external contributor PR; the original design prevented this entirely by gating the whole job.
  • The bot commit will trigger a second redundant workflow run per PR (no diff found, exits 0) that wastes CI minutes.
  • contents: write is declared at workflow scope rather than job scope, giving every step broader declared permissions than needed.

Confidence Score: 3/5

Not safe to merge as-is — fork PRs now run untrusted Makefile code on CI runners, reversing the intentional security gate of the original workflow.

A P1 security regression (fork code execution) is present in the core changed file; the fix is straightforward but requires restructuring the job or adding per-step guards before the issue is resolved.

.github/workflows/proto-check.yml — specifically the missing if guards on the Install buf and protoc plugins and Run proto generation steps

Security Review

  • Arbitrary code execution from fork PRs (.github/workflows/proto-check.yml, lines 44–51): The job-level fork guard was removed, so make install-buf install-plugins and make generate now execute the fork contributor's Makefile on a CI runner. A malicious PR can run arbitrary shell commands (network calls, resource abuse, environment probing) before any push restriction takes effect.
  • contents: write at workflow scope (line 12–13): Write permission is declared globally, applying to all steps including those serving fork PRs. GitHub's runtime restriction mitigates this for fork pull_request events today, but the declared scope is wider than necessary.

Important Files Changed

Filename Overview
.github/workflows/proto-check.yml Adds auto-commit of generated artifacts for internal PRs and splits checkout/verify steps by repo origin; security regression: removing the job-level fork guard now runs untrusted fork Makefile code on CI runners
CONTRIBUTING.md Adds documentation section explaining the generated-artifact auto-commit contract for internal vs. fork PRs; accurate and consistent with the workflow changes

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[pull_request event] --> B{Internal PR?}
    B -- Yes --> C[Checkout branch with token]
    B -- No --> D[Checkout fork merge commit]
    C --> E[setup-go + cache]
    D --> E
    E --> F[make install-buf install-plugins]
    F --> G[make generate]
    G --> H{Internal PR?}
    H -- Yes --> I{Generated files changed?}
    I -- No --> J[Exit 0 — up to date]
    I -- Yes --> K[git add + commit + push to PR branch]
    K --> L[Bot commit triggers new sync event → 2nd workflow run]
    H -- No --> M{git diff exit-code?}
    M -- Clean --> N[Exit 0 — up to date]
    M -- Dirty --> O[Fail with fork instructions]

    style D fill:#f99,stroke:#c00
    style F fill:#f99,stroke:#c00
    style G fill:#f99,stroke:#c00
    style L fill:#ffd,stroke:#aa0
Loading

Comments Outside Diff (1)

  1. .github/workflows/proto-check.yml, line 44-51 (link)

    P1 security Fork PR code execution — security regression

    The original workflow guarded the entire job with if: github.event.pull_request.head.repo.full_name == github.repository, so fork PRs never ran any steps. After this PR, the job-level gate is gone, meaning make install-buf install-plugins (line 45) and make generate (line 51) execute the fork's version of the Makefile on a CI runner for every external contributor PR. A malicious fork PR could modify Makefile to run arbitrary shell commands — network exfiltration, resource abuse, or probing the runner environment — none of which is prevented by the contents: read token restriction that fork PRs receive.

    The fork-PR verification steps at lines 69–94 correctly block pushing, but they run after the untrusted code has already executed. If the intent is to keep validation-only behaviour for forks, the safe pattern is to add if: github.event.pull_request.head.repo.full_name == github.repository to the Install buf and protoc plugins and Run proto generation steps (or restore the job-level condition and use a separate job with a pull_request_target trigger for forks).

Reviews (1): Last reviewed commit: "fix(ci): serialize proto freshness runs" | Re-trigger Greptile

Copy link
Copy Markdown

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

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: d3dff9ad74

ℹ️ 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".

if: github.event.pull_request.head.repo.full_name == github.repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
ref: ${{ github.event.pull_request.head.ref }}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Run generation on PR merge ref for internal branches

Checking out github.event.pull_request.head.ref makes the internal path generate artifacts from the branch tip instead of the PR merge result. When main has newer proto-related commits that the PR branch has not rebased yet, this step can auto-commit src/generated//docs/api/ files that are clean for the head branch but stale for what will actually merge, which undermines the freshness gate. Please validate against the merge commit (or add a separate merge-ref verification step) before pushing generated artifacts.

Useful? React with 👍 / 👎.

Comment thread .github/workflows/proto-check.yml Outdated
Comment on lines +12 to +13
permissions:
contents: read
contents: write
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.

P2 security Workflow-level contents: write is broader than needed

contents: write is declared at the top of the workflow and therefore applies to every step, including those that run for fork PRs (where GitHub's own security model restricts it to read-only in practice). Following the principle of least privilege, it is better to keep the workflow-level permission as contents: read and override to contents: write at the job level. This makes the intent explicit and limits blast radius if a future refactor moves steps around.

Comment thread .github/workflows/proto-check.yml Outdated
Comment on lines +53 to +67
- name: Commit generated artifacts for internal PRs
if: github.event.pull_request.head.repo.full_name == github.repository
env:
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
if git diff --quiet -- src/generated/ docs/api/ && [ -z "$(git ls-files --others --exclude-standard src/generated/ docs/api/)" ]; then
echo "Proto-generated code is up to date."
exit 0
fi

git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add src/generated/ docs/api/
git commit -m "chore(proto): update generated artifacts"
git push origin HEAD:"$PR_HEAD_REF"
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.

P2 Bot commit will re-trigger the same workflow

When the bot pushes chore(proto): update generated artifacts, GitHub fires a new pull_request synchronize event, causing this workflow to run a second time for the same PR. The second run will call make generate, find no diff, and exit cleanly — but it burns CI minutes and can confuse reviewers who see two consecutive proto-freshness runs. Adding [skip ci] to the bot commit message (or checking for github.actor == 'github-actions[bot]' at the job level) prevents the redundant run.

Copy link
Copy Markdown

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

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: ddac67158c

ℹ️ 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".


internal-merge-freshness:
needs: internal-auto-generate
if: github.event.pull_request.head.repo.full_name == github.repository && needs.internal-auto-generate.outputs.pushed != 'true'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Run merge-freshness after auto-commit in the same run

In .github/workflows/proto-check.yml, the internal-merge-freshness job is skipped whenever internal-auto-generate sets pushed=true, but the preceding push is done with GITHUB_TOKEN; GitHub does not create new workflow runs for events triggered by that token, so the expected follow-up pull_request run may never happen. For PRs where codegen changes are auto-committed, this can leave the merge-result freshness check unexecuted and allow stale generated artifacts relative to base to pass.

Useful? React with 👍 / 👎.

PROTO_CHANGED=$(printf '%s\n' "$CHANGED_FILES" | grep -E '^proto/' || true)
GENERATED_CHANGED=$(printf '%s\n' "$CHANGED_FILES" | grep -E '^(src/generated/|docs/api/)' || true)

if [ -n "$PROTO_CHANGED" ] && [ -z "$GENERATED_CHANGED" ]; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Enforce generated artifact updates on Makefile codegen changes

In the fork safety path, CHANGED_FILES includes Makefile, but the failure gate only checks PROTO_CHANGED, so fork PRs that modify generator behavior via Makefile (for example plugin/version changes) can pass without committing the resulting src/generated/ or docs/api/ updates. That creates a false green path for stale generated outputs whenever codegen inputs change outside proto/.

Useful? React with 👍 / 👎.

@lspassos1
Copy link
Copy Markdown
Collaborator Author

Follow-up pushed in ddac6715 to address the workflow safety review.

Changes:

  • Restored top-level workflow permissions to contents: read.
  • Split fork PR handling from internal PR handling. Fork PRs no longer execute the PR's Makefile, buf.gen.yaml, or generator configuration.
  • Kept auto-generation for internal PRs only, with job-scoped contents: write.
  • Added an internal merge-result freshness job so generated artifacts are checked against the actual PR merge result when no artifact commit was pushed.
  • Updated CONTRIBUTING.md to document the fork/internal contract.

Validation:

  • Parsed .github/workflows/proto-check.yml with Ruby YAML.
  • Ran git diff --check on the workflow and contributing guide.

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.

Move sebuf codegen out of PRs into CI/CD

1 participant